<p align="center">
<img alt="arguably logo" src="https://raw.githubusercontent.com/treykeown/arguably/main/etc/logo/arguably_black.png">
</p>
<p align="center">
<em>
The best Python CLI library, arguably.
</em>
</p>
<p align="center">
<a href="https://github.com/treykeown/arguably/actions/workflows/python-package.yml"><img src="https://github.com/treykeown/arguably/actions/workflows/python-package.yml/badge.svg" alt="Test status"></a>
<a href="https://treykeown.github.io/arguably/coverage/"><img src="https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/treykeown/f493b14288af4e8358ea8578c393213a/raw/arguably-coverage-badge.json" alt="Code coverage"></a>
<a href="https://pypi.org/project/arguably/"><img src="https://shields.io/pypi/pyversions/arguably" alt="Supported Python versions"></a>
<a href="https://pypi.org/project/arguably/"><img src="https://shields.io/pypi/v/arguably" alt="PyPI version"></a>
</p>
<hr>
`arguably` turns functions and docstrings into command line interfaces (CLIs). `arguably` has a tiny API and is
extremely easy to integrate. You can also use it directly through `python3 -m arguably your_script.py`, more on that
[here](#no-integration-required).
To use `arguably` in a script, decorate any functions that should appear on the command line with `@arguably.command`,
then call `arguably.run()`. If multiple functions are decorated, they'll all appear as subcommands. You can even have
*multiple levels* of subcommands: `def s3__ls()` becomes `s3 ls`.
<div align="right"><sub>
<a href="https://github.com/treykeown/arguably/blob/main/etc/scripts/intro.py">[source]</a>
</sub></div>
```python
#!/usr/bin/env python3
import arguably
@arguably.command
def some_function(required, not_required=2, *others: int, option: float = 3.14):
"""
this function is on the command line!
Args:
required: a required argument
not_required: this one isn't required, since it has a default value
*others: all the other positional arguments go here
option: [-x] keyword-only args are options, short name is in brackets
"""
print(f"{required=}, {not_required=}, {others=}, {option=}")
if __name__ == "__main__":
arguably.run()
```
<p align="center"><b><em>becomes</em></b></p>
```console
user@machine:~$ ./intro.py -h
usage: intro.py [-h] [-x OPTION] required [not-required] [others ...]
this function is on the command line!
positional arguments:
required a required argument (type: str)
not-required this one isn't required, since it has a default value (type: int, default: 2)
others all the other positional arguments go here (type: int)
options:
-h, --help show this help message and exit
-x, --option OPTION keyword-only args are options, short name is in brackets (type: float, default: 3.14)
```
Arguments to the CLI look just like calling the Python function.
```pycon
>>> from intro import some_function
>>> some_function("asdf", 0, 7, 8, 9, option=2.71)
required='asdf', not_required=0, others=(7, 8, 9), option=2.71
```
```console
user@machine:~$ ./intro.py asdf 0 7 8 9 --option 2.71
required='asdf', not_required=0, others=(7, 8, 9), option=2.71
```
`arguably` uses your docstrings to automatically generate help messages. It supports all major formats for docstrings:
reStructuredText, Google, Numpydoc, and Epydoc.
Type annotations are optional, but `arguably` can use them to automatically convert arguments. It has smart handling for
mapping built-in types to the command line, including `tuple`, `list`, `enum.Enum`, and `enum.Flag`.
There are also a few special behaviors you can attach to a parameter via `Annotated[]` and the `arguably.arg.*`
functions. Using `arguably.arg.builder()`, you can even build an object to pass in from the command line (using syntax
inspired by QEMU):
<div align="right"><sub>
<a href="https://github.com/treykeown/arguably/blob/main/etc/scripts/build.py">[source]</a>
</sub></div>
```console
user@machine:~$ ./build.py --nic tap,model=e1000 --nic user,hostfwd=tcp::10022-:22
nic=[TapNic(model='e1000'), UserNic(hostfwd='tcp::10022-:22')]
```
## No integration required
Don't want to write any code? Simply pass any Python script to `arguably` to give it a command line interface.
<div align="right"><sub>
<a href="https://github.com/treykeown/arguably/blob/main/etc/scripts/party-trick.py">[source]</a>
</sub></div>
```console
user@machine:~$ python3 -m arguably party-trick.py -h
usage: party-trick [-h] [--version] command ...
this is the docstring for the whole script
positional arguments:
command
hello this is hello's docstring
goodbye any function from a script can be called
some-class so can any __init__ for objects defined in the script
some-class.func-static a @staticmethod on a class can be called
some-class.func-cls so can a @classmethod
options:
-h, --help show this help message and exit
--version show program's version number and exit
```
## Installation
Install using `pip install arguably`. If you want to install using `conda`, please comment on
[this issue](https://github.com/treykeown/arguably/issues/12).
## Documentation
* Why arguably?: [https://treykeown.github.io/arguably/why/](https://treykeown.github.io/arguably/why/)
* Examples: [https://treykeown.github.io/arguably/examples/](https://treykeown.github.io/arguably/examples/)
* Tutorial: [https://treykeown.github.io/arguably/tutorial/intro/](https://treykeown.github.io/arguably/tutorial/intro/)
* API Reference: [https://treykeown.github.io/arguably/api-reference/](https://treykeown.github.io/arguably/api-reference/)
## Dependencies
All of `arguably` is built on top of `argparse`. It has two dependencies:
* `docstring-parser` for parsing function docstrings
* `typing-extensions` for `Annotated[]` support in Python 3.8 (only needed for that version)
## Contributing
Ideas and help are very much appreciated! There's a guide for getting started with contributing to `arguably` that shows
you how to run tests and pre-commit hooks.
* Contributing: [https://treykeown.github.io/arguably/contributing/](https://treykeown.github.io/arguably/contributing/)
## Future roadmap
If you have any interest in these (either as a user or implementer), please leave a comment!
* [#8 - Display all enum options in a command group](https://github.com/treykeown/arguably/issues/8)
* [#9 - Both positive and negative boolean flags](https://github.com/treykeown/arguably/issues/9)
* [#10 - Take inputs from environment variables](https://github.com/treykeown/arguably/issues/10)
* [#13 - Implement config interface](https://github.com/treykeown/arguably/issues/13)
* [#16 - Integration with rich for formatted CLI output](https://github.com/treykeown/arguably/issues/16)
Raw data
{
"_id": null,
"home_page": "https://treykeown.github.io/arguably/",
"name": "arguably",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "",
"author": "treykeown",
"author_email": "2755914+treykeown@users.noreply.github.com",
"download_url": "https://files.pythonhosted.org/packages/ff/87/a11fd8a613f4da31057a7408d4eb257e7bec87254a4ed46d2944ea36a6cf/arguably-1.2.5.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <img alt=\"arguably logo\" src=\"https://raw.githubusercontent.com/treykeown/arguably/main/etc/logo/arguably_black.png\">\n</p>\n\n<p align=\"center\">\n <em>\n The best Python CLI library, arguably.\n </em>\n</p>\n\n<p align=\"center\">\n <a href=\"https://github.com/treykeown/arguably/actions/workflows/python-package.yml\"><img src=\"https://github.com/treykeown/arguably/actions/workflows/python-package.yml/badge.svg\" alt=\"Test status\"></a>\n <a href=\"https://treykeown.github.io/arguably/coverage/\"><img src=\"https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/treykeown/f493b14288af4e8358ea8578c393213a/raw/arguably-coverage-badge.json\" alt=\"Code coverage\"></a>\n <a href=\"https://pypi.org/project/arguably/\"><img src=\"https://shields.io/pypi/pyversions/arguably\" alt=\"Supported Python versions\"></a>\n <a href=\"https://pypi.org/project/arguably/\"><img src=\"https://shields.io/pypi/v/arguably\" alt=\"PyPI version\"></a>\n</p>\n<hr>\n\n`arguably` turns functions and docstrings into command line interfaces (CLIs). `arguably` has a tiny API and is\nextremely easy to integrate. You can also use it directly through `python3 -m arguably your_script.py`, more on that\n[here](#no-integration-required).\n\nTo use `arguably` in a script, decorate any functions that should appear on the command line with `@arguably.command`,\nthen call `arguably.run()`. If multiple functions are decorated, they'll all appear as subcommands. You can even have\n*multiple levels* of subcommands: `def s3__ls()` becomes `s3 ls`.\n\n<div align=\"right\"><sub>\n <a href=\"https://github.com/treykeown/arguably/blob/main/etc/scripts/intro.py\">[source]</a>\n</sub></div>\n\n```python\n#!/usr/bin/env python3\nimport arguably\n\n@arguably.command\ndef some_function(required, not_required=2, *others: int, option: float = 3.14):\n \"\"\"\n this function is on the command line!\n\n Args:\n required: a required argument\n not_required: this one isn't required, since it has a default value\n *others: all the other positional arguments go here\n option: [-x] keyword-only args are options, short name is in brackets\n \"\"\"\n print(f\"{required=}, {not_required=}, {others=}, {option=}\")\n\nif __name__ == \"__main__\":\n arguably.run()\n```\n\n<p align=\"center\"><b><em>becomes</em></b></p>\n\n```console\nuser@machine:~$ ./intro.py -h\nusage: intro.py [-h] [-x OPTION] required [not-required] [others ...]\n\nthis function is on the command line!\n\npositional arguments:\n required a required argument (type: str)\n not-required this one isn't required, since it has a default value (type: int, default: 2)\n others all the other positional arguments go here (type: int)\n\noptions:\n -h, --help show this help message and exit\n -x, --option OPTION keyword-only args are options, short name is in brackets (type: float, default: 3.14)\n```\n\nArguments to the CLI look just like calling the Python function.\n\n```pycon\n>>> from intro import some_function\n>>> some_function(\"asdf\", 0, 7, 8, 9, option=2.71)\nrequired='asdf', not_required=0, others=(7, 8, 9), option=2.71\n```\n\n```console\nuser@machine:~$ ./intro.py asdf 0 7 8 9 --option 2.71\nrequired='asdf', not_required=0, others=(7, 8, 9), option=2.71\n```\n\n`arguably` uses your docstrings to automatically generate help messages. It supports all major formats for docstrings:\nreStructuredText, Google, Numpydoc, and Epydoc.\n\nType annotations are optional, but `arguably` can use them to automatically convert arguments. It has smart handling for\nmapping built-in types to the command line, including `tuple`, `list`, `enum.Enum`, and `enum.Flag`.\n\nThere are also a few special behaviors you can attach to a parameter via `Annotated[]` and the `arguably.arg.*`\nfunctions. Using `arguably.arg.builder()`, you can even build an object to pass in from the command line (using syntax\ninspired by QEMU):\n\n<div align=\"right\"><sub>\n <a href=\"https://github.com/treykeown/arguably/blob/main/etc/scripts/build.py\">[source]</a>\n</sub></div>\n\n```console\nuser@machine:~$ ./build.py --nic tap,model=e1000 --nic user,hostfwd=tcp::10022-:22\nnic=[TapNic(model='e1000'), UserNic(hostfwd='tcp::10022-:22')]\n```\n\n## No integration required\n\nDon't want to write any code? Simply pass any Python script to `arguably` to give it a command line interface.\n\n<div align=\"right\"><sub>\n <a href=\"https://github.com/treykeown/arguably/blob/main/etc/scripts/party-trick.py\">[source]</a>\n</sub></div>\n\n```console\nuser@machine:~$ python3 -m arguably party-trick.py -h\nusage: party-trick [-h] [--version] command ...\n\nthis is the docstring for the whole script\n\npositional arguments:\n command\n hello this is hello's docstring\n goodbye any function from a script can be called\n some-class so can any __init__ for objects defined in the script\n some-class.func-static a @staticmethod on a class can be called\n some-class.func-cls so can a @classmethod\n\noptions:\n -h, --help show this help message and exit\n --version show program's version number and exit\n```\n\n## Installation\n\nInstall using `pip install arguably`. If you want to install using `conda`, please comment on\n[this issue](https://github.com/treykeown/arguably/issues/12).\n\n## Documentation\n\n* Why arguably?: [https://treykeown.github.io/arguably/why/](https://treykeown.github.io/arguably/why/)\n* Examples: [https://treykeown.github.io/arguably/examples/](https://treykeown.github.io/arguably/examples/)\n* Tutorial: [https://treykeown.github.io/arguably/tutorial/intro/](https://treykeown.github.io/arguably/tutorial/intro/)\n* API Reference: [https://treykeown.github.io/arguably/api-reference/](https://treykeown.github.io/arguably/api-reference/)\n\n## Dependencies\n\nAll of `arguably` is built on top of `argparse`. It has two dependencies:\n\n* `docstring-parser` for parsing function docstrings\n* `typing-extensions` for `Annotated[]` support in Python 3.8 (only needed for that version)\n\n## Contributing\n\nIdeas and help are very much appreciated! There's a guide for getting started with contributing to `arguably` that shows\nyou how to run tests and pre-commit hooks.\n\n* Contributing: [https://treykeown.github.io/arguably/contributing/](https://treykeown.github.io/arguably/contributing/)\n\n## Future roadmap\n\nIf you have any interest in these (either as a user or implementer), please leave a comment!\n\n* [#8 - Display all enum options in a command group](https://github.com/treykeown/arguably/issues/8)\n* [#9 - Both positive and negative boolean flags](https://github.com/treykeown/arguably/issues/9)\n* [#10 - Take inputs from environment variables](https://github.com/treykeown/arguably/issues/10)\n* [#13 - Implement config interface](https://github.com/treykeown/arguably/issues/13)\n* [#16 - Integration with rich for formatted CLI output](https://github.com/treykeown/arguably/issues/16)\n",
"bugtrack_url": null,
"license": "",
"summary": "The best Python CLI library, arguably.",
"version": "1.2.5",
"project_urls": {
"Homepage": "https://treykeown.github.io/arguably/",
"Repository": "https://github.com/treykeown/arguably"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "27b4f5277af855a1a06e2106fbc72bcd937e2856f159e7d4e12f7e2bff872862",
"md5": "50b94c6071e637703737853a8c7a9a88",
"sha256": "ab6667a0c6762fd79e78fae38eafe61dcf2295ebccef24a350298cd1068b4994"
},
"downloads": -1,
"filename": "arguably-1.2.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "50b94c6071e637703737853a8c7a9a88",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 35329,
"upload_time": "2023-06-29T11:10:16",
"upload_time_iso_8601": "2023-06-29T11:10:16.384482Z",
"url": "https://files.pythonhosted.org/packages/27/b4/f5277af855a1a06e2106fbc72bcd937e2856f159e7d4e12f7e2bff872862/arguably-1.2.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "ff87a11fd8a613f4da31057a7408d4eb257e7bec87254a4ed46d2944ea36a6cf",
"md5": "7fb501d20887ee5d7fdadc80a48482d6",
"sha256": "d55963abbab823b8ad1da798216cd6a7106b3238178855d6ad495beed60ab423"
},
"downloads": -1,
"filename": "arguably-1.2.5.tar.gz",
"has_sig": false,
"md5_digest": "7fb501d20887ee5d7fdadc80a48482d6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 30786,
"upload_time": "2023-06-29T11:10:18",
"upload_time_iso_8601": "2023-06-29T11:10:18.405327Z",
"url": "https://files.pythonhosted.org/packages/ff/87/a11fd8a613f4da31057a7408d4eb257e7bec87254a4ed46d2944ea36a6cf/arguably-1.2.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-29 11:10:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "treykeown",
"github_project": "arguably",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "arguably"
}