Metadata-Version: 2.1
Name: aphelper
Version: 0.0.3
Summary: A Python package to enable declarative definition of argparse CLIs
Home-page: https://github.com/jfcarter2358/aphelper
Author: John Carter
Author-email: jfcarter2358@gmail.com
License: MIT
Description: # APHelper
        
        ## Getting Started
        
        To use APHeler, add the following import statement to your code
        ```python
        from aphelper import core
        ```
        
        Then, make sure your program has a main class with whatever functions you want to the commands to run contained in it. For example, here is a file with a `Test` class that has a `test` function inside it which our command will call.
        ```python
        from aphelper import core
        
        class Test:
            def __init__(self):
                ah = core.ArgparseHelper(def_file='test/test.jsonc', parent=self)
                ah.execute()
        
            def test(self, args):
                print('test')
        
        if __name__ == '__main__':
            Test()
        ```
        
        You'll see that in the class' init function we create a `core.ArgparseHelper` object and pass the location of a definition file along with 'self'. You can pass a file location with the `def_file` keyword or you can pass the contents of a file with the `def_data` keyword.
        Following the creation of the object, we call `ah.execute()` to create and parse the CLI.
        
        The definition file used in this example is below:
        ```jsonc
        {
            // the meta section defines information about the parser/subparser
            // for this first meta section you don't need the parser_help key/field
            "meta": {
                "parser_description": "Foo bar",
                "subparser_title": "subcommands",
                "subparser_dest": "command",
                "subparser_description": "valid subcommands"
            },
            // the subparsers key is used to define any parsers that need to be created
            "subparsers": {
                // in this case "hello" is the name of the first command
                "hello": {
                    "meta": {
                        "parser_description": "hello description",
                        "parser_help": "hello help",
                        "subparser_title": "subcommands",
                        "subparser_dest": "subcommand",
                        "subparser_description": "valid subcommands"
                    },
                    // once again we have a subparsers section which means we want another command
                    // underneath "hello" which is not a final subcommand
                    "subparsers": {
                        "world": {
                            "meta": {
                                "parser_description": "world description",
                                "parser_help": "world help",
                                "subparser_title": "subcommands",
                                "subparser_dest": "subsubcommand",
                                "subparser_description": "valid subcommands"
                            },
                            // subcommands are for defining the "lowest level" commands which actually
                            // have arguments
                            // in this case, we are defining the "test" in the command string "hello world test"
                            "subcommands": {
                                "test": {
                                    "meta": {
                                        "description": "test help",
                                        "help": "test description",
                                        "function": {
                                            "name": "test",
                                            "args": {}
                                        },
                                        "requires": {
                                            "foo1": {
                                                "AND": ["bar1", "bar2"],
                                                "message": "the 'foo1' argument requires '--bar1' and '--bar2'"
                                            },
                                            "foo2": {
                                                "OR": ["bar1", "bar2"],
                                                "message": "the 'foo2' argument requires either '--bar1' or '--bar2'"
                                            },
                                            "foo3": {
                                                "NAND": ["bar1", "bar2"],
                                                "message": "the 'foo3' argument requires either '--bar1' or '--bar2' or neither, but not both"
                                            },
                                            "foo4": {
                                                "NOR": ["bar1", "bar2"],
                                                "message": "the 'foo4' argument requires '--bar1' and '--bar2' to be false"
                                            },
                                            "foo5": {
                                                "NOT": ["bar1"],
                                                "message": "the 'foo5' argument requires '--bar1' to be false"
                                            },
                                            "foo6": {
                                                "XOR": ["bar1", "bar2"],
                                                "message": "the 'foo6' argument requires '--bar1' or '--bar2', but not both"
                                            }
                                        }
                                    },
                                    "args": {
                                        "foo1": {
                                            "short": "-f",
                                            "long": "--foo1",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "foo2": {
                                            "long": "--foo2",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "foo3": {
                                            "long": "--foo3",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "foo4": {
                                            "long": "--foo4",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "foo5": {
                                            "long": "--foo5",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "foo6": {
                                            "long": "--foo6",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "bar1": {
                                            "long": "--bar1",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        },
                                        "bar2": {
                                            "long": "--bar2",
                                            "choices": null,
                                            "default": null,
                                            "help": null,
                                            "action": "store_true",
                                            "nargs": null
                                        }
                                    }
                                }
                            }
                        } 
                    }
                }
            }
        }
        ```
        
        ## Definition File Structure
        
        `APHelper` allows for nested definitions within the definition file in order to create a multi-layered command line interface.  The two main object types that can be defined are `subparsers` and `subcommands`.  `Subparsers` are any CLI level that does not handle arguments directly and instead is a parent to other `subparsers` or `subcommands`. `subcommands` are different in that they are the final children of `subparsers` and cannot contain any other `subcommands`, instead they hold the argument definitions for the command.
        
        When writing a definition file, you must always start with this template:
        ```
        {
            // the meta section defines information about the parser/subparser
            // for this first meta section you don't need the parser_help key/field
            "meta": {
                "parser_description": "",
                "subparser_title": "",
                "subparser_dest": "",
                "subparser_description": ""
            }
        }
        ```
        
        On the same level as the "meta" command you can then add a `subaparsers` or `subcommands` section depending on your needs. 
        
        The structure of a `subparsers` section is shown below.
        ``` jsonc
         "subparsers": {
            // in this case "hello" is the name of the first command
            "hello": {
                "meta": {
                    // these five fields are required for any subparser
                    // However, you can always set them to an empty string
                    "parser_description": "hello description",
                    "parser_help": "hello help",
                    "subparser_title": "subcommands",
                    "subparser_dest": "subcommand",
                    "subparser_description": "valid subcommands"
                },
                // if you want to have sub-subparsers, you can define another subparsers section
                // if not, then just don't add it
                "subparsers": {},
                // if you want to have subcommands, you can define a subcommandssection
                // if not, then just don't add it
                "subcommands": {}
            },
            // if you want more than one command on this level then you can just add another key
            // along with its "meta" section and any desired "subparsers" and "subcommands"
            "hello2": {
                // ...
            },
            // ...
         }
        ```
        
        The structure of a `subcommands` section is shown below.
        ```jsonc
         "subcommands": {
            // in this case "hello" is the name of the first command
            "world": {
                "meta": {
                    // command description (required)
                    "description": "",
                    // command help (required)
                    "help": "",
                    "function": { // (required)
                        // name of the function inside the class that calls the ArgparseHelper object
                        // that you want to call when the command is executed
                        "name": ""
                    },
                    "requires": { // (required, but you can just leave it blank if you want)
                        // here we define any arguments that require logic to make sure that combinations of arguments are valid
                        // set the argument that you want to trigger the logical check as the key
                        "foo1": { 
                            // then define any logical checks you want to be made
                            // The valid operators are:
                            //   - AND
                            //   - NAND
                            //   - NOR
                            //   - NOT
                            //   - OR
                            //   - XOR
                            "AND": ["bar1", "bar2"],
                            // the message to print out if the logical check fails
                            "message": "the 'foo1' argument requires '--bar1' and '--bar2'"
                        }
                    }
                },
                "args": {
                    "foo1": {
                        // you need either a "short" key or a "long" key or both
                        "short": "-f", // this is the single-letter flag that can be used for this argument
                        "long": "--foo1", // this is the long flag that can be used for this argument
                        // you can define any argparse keyword for the `add_argument` functio as a key and for an agrument
                        // and it will be added to your argument that is created in your applicatoin
                        // for example, in this case we set the 'action' keyword to 'store_true' for a boolean flag
                        "action": "store_true"
                    },
                    "bar1": {
                        "long": "--bar1",
                        "action": "store_true"
                    },
                    "bar2": {
                        "long": "--bar2",
                        "action": "store_true"
                    }
                }
            },
            // if you want more than one command on this level then you can just add another key
            // along with its "meta" and "args" sections
            "world2": {
                // ...
            },
            // ...
         }
        ```
        
        You can then nest these `subcommands` and `subparsers` sections together to create whatever structure you need
Platform: UNKNOWN
Requires-Python: >=3.7
Description-Content-Type: text/markdown
