{ "info": { "author": "Colin Caine", "author_email": "", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# CLI\n\n> An extremely easy to use library to generate python CLIs from functions through introspection.\n\nAutomatically generate the equivalent of this:\n\n```python\nimport argparse\nparser = argparse.ArgumentParser(description=\"Generate a cryptographic token with a given entropy.\")\nparser.add_argument('method', nargs='?', default='xkcd', choices=('xkcd', 'short'))\nparser.add_argument('entropy', nargs='?', default=70, type=int)\nargs = parser.parse_args()\n\nif args.method == 'xkcd':\n print(xkcd(args.entropy))\nelse:\n print(alphanumeric(args.entropy))\n```\n\nfrom this:\n\n```python\nfrom cli import Choice, cli\n\ndef token(method:Choice('xkcd', 'short')='xkcd', entropy=70):\n \"Generate a cryptographic token with a given entropy.\"\n if method == 'xkcd':\n\treturn xkcd(entropy)\n else:\n\treturn alphanumeric(entropy)\n\ncli(token)()\n```\n\nExplicitly, `cli(token)` creates a new function that accepts an array of strings, parses *and automatically converts* them according to rules derived from the function signature, applies the parsed arguments to the original `token` and prints the output. `cli(token)()` calls that function using the default `sys.argv`.\n\n## But wait, there's more!\n\nKeyword arguments (optional or mandatory) are supported as is one varargs argument per function. **Arguments will be automatically converted** into the type of their default argument (if it is not None) or their type annotation.\n\nThe exact mapping from function signature to argparse rules is specified in the docstring of `generate_parser()`, but the idea is that it should be fairly intuitive.\n\nYou can even generate CLIs for a whole module (or any other object with function attributes):\n\n```python\nimport example\nfrom cli import cli, opportunistic, coerce_number\n\n# You can use opportunistic(coerce_number) to convert any string that looks\n# like a number to a number so you don't have to annotate all the functions in a\n# module. YMMV.\ncli(example, default_type=opportunistic(coerce_number))()\n\n# If you want one, you can get a reference to the current module with\n# sys.modules[__name__]\n```\n\n## Lower level API\n\n`generate_parser(your_function_here)` will return an `argparse.Parser` instance. `apply_namespace(your_function_here, namespace)` will apply a namespace object (as returned by `parser.parse_args()`) to a function.\n\n`generate_parser_obj(your_module_or_class_here)` will return an `argparse.Parser` with one subparser per callable on the\n\n## Code quality\n\nThe code is very short, clearly documented inline and all advertised features are tested.\n\n## Reference\n\nFunction signature interpretation:\n - (`POSITIONAL_ONLY`, `POSITIONAL_OR_KEYWORD`) = positional\n - positional with default = optional positional\n - `KEYWORD_ONLY` = options\n - defaults = defaults\n\t- Boolean special casing\n\t - If the default is `True` or `False`, the option does not take any\n\t arguments. Instead, if the option is given on the\n\t commandline, the opposite value to the default is given to\n\t the function.\n\t - Example:\n\t\t```python\n\t\tdef rm(*, force=False):\n\t\t pass\n\n\t\tcli(rm)(['--force']) # ~== rm(force=True)\n\t\tcli(rm)([]) # ~== rm(force=False)\n\t\t```\n - type annotations = type\n\t- If the `type` is callable, it is called by `argparse` on the relevant substring\n\t- If the type is `bool`, it is replaced by `coerce_bool`\n\t- Provide your own custom function or handle the strings in your\n\t function body if you need something fancier.\n\nSpecial types:\n - cli.Choice\n\t- `def foo(x:Choice(1,2))` interpreted as `add_argument('x', choices=(1,2), type=int)`\n\n```python\ndef example(positional, arguments):\n pass\n\ndef defaults(normally_one=1):\n pass\n\ndef typed(positional:bool, positional2:int):\n pass\n\n# keyword some-positional-arg --keyword2=foo --keyword1=4\ndef keyword(positional, *, keyword1=3, keyword2='default_filename'):\n pass\n\n# Mandatory keywords are bad, but you can have them if you want.\ndef mandatory_keywords(positional, *, keyword1, keyword2):\n pass\n\ndef varargs(pos1, pos2, *rest):\n pass\n\ndef choice_from_list(person:Choice('Ann', 'Bob', 'Charlie'))\n pass\n\n# `flags --flag` is similar to flags(flag=True)\n# `flags --inverse_flag` is similar to flags(inverse_flag=False)\ndef flags(*, flag=False, inverse_flag=True):\n pass\n```\n\n## Related work\n\nOther nice ways to make CLIs:\n\n - [docopt](https://docopt.org)\n - [cli2](https://pypi.org/project/cli2/)\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/cmcaine/cli", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "cmcaine-cli", "package_url": "https://pypi.org/project/cmcaine-cli/", "platform": "", "project_url": "https://pypi.org/project/cmcaine-cli/", "project_urls": { "Homepage": "https://github.com/cmcaine/cli" }, "release_url": "https://pypi.org/project/cmcaine-cli/0.0.2/", "requires_dist": null, "requires_python": "", "summary": "Easy CLIs from function inspection", "version": "0.0.2" }, "last_serial": 5230096, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "0632cf3a495b4f0dff4dbb7834b3d132", "sha256": "07c02b53dc7d5527c10ef1b3a658e481836bb23cb2b408fef7fcf29e8cd29c29" }, "downloads": -1, "filename": "cmcaine_cli-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "0632cf3a495b4f0dff4dbb7834b3d132", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 4444, "upload_time": "2019-05-05T13:28:59", "url": "https://files.pythonhosted.org/packages/31/7a/f450d62d889174b6888d2f75f654cfba8bf9d382206ead2a2c15f4993496/cmcaine_cli-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "346bae35c46d2105c2889bff6f3668e9", "sha256": "f635c9d36f5a244ea49545558cdbd82bd9a974f32ad8f65ff3b5e10ebd7252b8" }, "downloads": -1, "filename": "cmcaine-cli-0.0.1.tar.gz", "has_sig": false, "md5_digest": "346bae35c46d2105c2889bff6f3668e9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 3947, "upload_time": "2019-05-05T13:29:01", "url": "https://files.pythonhosted.org/packages/0e/21/2e63ad0516c9fc37d3ad61e11db8ceaf13c233609afdff90d5ec887d3cd8/cmcaine-cli-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "a5c01f5deede59f841ae9c62b4f6f8e9", "sha256": "03c327dc5810932f25d1cdcba89a3209103294e14913fb5c68e379b2e39ae375" }, "downloads": -1, "filename": "cmcaine_cli-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "a5c01f5deede59f841ae9c62b4f6f8e9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6978, "upload_time": "2019-05-06T00:03:35", "url": "https://files.pythonhosted.org/packages/9b/32/cd8394cd97bcd2307821e764c35b9081ac0cfef35aeffa217bf4599c605b/cmcaine_cli-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d6c29476425c57c4c7133e31bd4e30d1", "sha256": "c97fd417710fef899f0bdeca9db068e8e27a21ed394003d2e5223118b8acbda6" }, "downloads": -1, "filename": "cmcaine-cli-0.0.2.tar.gz", "has_sig": false, "md5_digest": "d6c29476425c57c4c7133e31bd4e30d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5395, "upload_time": "2019-05-06T00:03:37", "url": "https://files.pythonhosted.org/packages/db/85/3fa8bf77d97cdc4bf69740dd0b5fe5caee8032b90e58dfffcbafed59ae92/cmcaine-cli-0.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a5c01f5deede59f841ae9c62b4f6f8e9", "sha256": "03c327dc5810932f25d1cdcba89a3209103294e14913fb5c68e379b2e39ae375" }, "downloads": -1, "filename": "cmcaine_cli-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "a5c01f5deede59f841ae9c62b4f6f8e9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6978, "upload_time": "2019-05-06T00:03:35", "url": "https://files.pythonhosted.org/packages/9b/32/cd8394cd97bcd2307821e764c35b9081ac0cfef35aeffa217bf4599c605b/cmcaine_cli-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d6c29476425c57c4c7133e31bd4e30d1", "sha256": "c97fd417710fef899f0bdeca9db068e8e27a21ed394003d2e5223118b8acbda6" }, "downloads": -1, "filename": "cmcaine-cli-0.0.2.tar.gz", "has_sig": false, "md5_digest": "d6c29476425c57c4c7133e31bd4e30d1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5395, "upload_time": "2019-05-06T00:03:37", "url": "https://files.pythonhosted.org/packages/db/85/3fa8bf77d97cdc4bf69740dd0b5fe5caee8032b90e58dfffcbafed59ae92/cmcaine-cli-0.0.2.tar.gz" } ] }