Skip to main content

A Python package to enable declarative definition of argparse CLIs

Project description

APHelper

Getting Started

To use APHeler, add the following import statement to your code

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.

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:

{
    // 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.

 "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.

 "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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aphelper-0.0.6.tar.gz (7.1 kB view details)

Uploaded Source

Built Distribution

aphelper-0.0.6-py3-none-any.whl (6.9 kB view details)

Uploaded Python 3

File details

Details for the file aphelper-0.0.6.tar.gz.

File metadata

  • Download URL: aphelper-0.0.6.tar.gz
  • Upload date:
  • Size: 7.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.7.7

File hashes

Hashes for aphelper-0.0.6.tar.gz
Algorithm Hash digest
SHA256 aa4e3f35a8ac24e253a27acde6b67ccc7831974188565147c4d4e3249b186db8
MD5 eb7dddbee99f0bc114d85616be545d3c
BLAKE2b-256 389cd850f3e69ba43bffe66b27acd9681932cba905a4980f1709b297c4c433b8

See more details on using hashes here.

File details

Details for the file aphelper-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: aphelper-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 6.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.2.0 pkginfo/1.6.1 requests/2.24.0 setuptools/41.2.0 requests-toolbelt/0.9.1 tqdm/4.51.0 CPython/3.7.7

File hashes

Hashes for aphelper-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 d29137112c28b4503b8693f405866ab5e4ca94a2e5aaecfd2e2e2023af3183ce
MD5 eb85a4059014a7f5d9cb6605e1b3af27
BLAKE2b-256 b92c1c4f7214b191ebf2a93c0990c81a0ec91f979ac32a18a5383f8b5cc5a2b1

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page