with-argparse


Namewith-argparse JSON
Version 1.0.2 PyPI version JSON
download
home_pageNone
SummaryA simple but handy Python library to generate a `argparse.ArgumentParser` object from a type-annotated method
upload_time2025-01-24 12:44:49
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseApache 2.0
keywords argparse type annotation auto
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # with-argparse

`with-argparse` is a very simple and tiny package using `argparse.ArgumentParser` objects
to derive a CLI that is automatically applied to a function using type annotations. 
*Currently supports Python 3.10-11*.

### Supported features:

- Argument lists via `nargs=+`
- Argument choices via `typing.Literal[x, y, z]`
- Optional values and required arguments
- Boolean flags via presence or abscence of `--argument_name`
- Custom parse functions via `@with_argparse(arg_name=custom_fn)`
- Ignored values: `@with_argparse(ignore_keys={'arg_name'}`
- Nested type annotations such as `list[int]`
- Disabled mode: `with_argparse.no_argparse()` context manager

In order for this package to work, functions must receive an explicit type annotation.
The following type annotations are currently supported:

- `str, int, float, bool, ...`
- Types that have constructors that accept a single `str` as input
- `list[type]` and `set[type]`
- `Optional[type], type | None, Union[type, None]`,
- `Literal[type_val1, type_val2]`
- Custom types via custom parse functions (supplied via `kwarg` to the `@with_argparse` decorator.

### Example code

```python3
from typing import Optional
from with_argparse import with_argparse

def custom_parse_fn(inp: str) -> int:
    return 42 if inp == "yeah" else -1

@with_argparse(
    ignore_keys={"ignored_value"}, 
    complex_input=custom_parse_fn
)
def cli(
    theory_of_everything: int,
    complex_input: int,
    ignored_value: Optional[str] = None,
) -> int:
    print(ignored_value)
    return theory_of_everything * complex_input

cli(ignored_value="abc")
```

will generate the following CLI output when run:

```text
usage: --theory_of_everything THEORY_OF_EVERYTHING
                    [--complex_input COMPLEX_INPUT]
```

### Custom parse functions

Becomes increasingly useful when the target type `T` does not have a default constructor with a single `str` argument
or more complex logic is required to parse the desired type from a string input.

As it is not type correct to use functions as type annotations (it would work extracting those functions from there, 
however type checkers such as mypy will complain when doing so), one can specify custom parse functions
directly in the `@with_argparse()` decorator via a keyword argument named as the target parameter.

Say we have a complex function that does call some other functions before eventually returning the string in reverse:
```python

def func_a(a: str) -> str: ...
def func_b(b: str) -> str: ...

def custom_fn(inp: str):
    inp = func_a(inp)
    inp = func_b(inp)
    return str(reversed(inp))
```

Our custom function can also accept types differing from `str`, such as `int`.

We can then use this function to parse the input the following way in our dummy `cli` function:

```python
@with_argparse(complex_input=custom_fn)
def cli(complex_input: str) -> str:
    return complex_input
```

### Boolean values

For Boolean values, if the default specified is `True`, the CLI argument name is renamed to `--no_argname`,
such that the user must specify to *disable* the given argument. In any other case (`None, False`), the user must
specify `--arg_name` to set the Boolean argument to `True`,

The renaming of a parameter can be disabled by specifying its name in the set `ignore_mapping`, again in the 
`@with_argparse` decorator to the function.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "with-argparse",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "argparse, type annotation, auto",
    "author": null,
    "author_email": "Moritz Hennen <mail@fleance.de>",
    "download_url": "https://files.pythonhosted.org/packages/a8/f9/83c6ee1eaa0c929bf513b7e024eba923e347ed11a557c03150593d71b3a5/with_argparse-1.0.2.tar.gz",
    "platform": null,
    "description": "# with-argparse\n\n`with-argparse` is a very simple and tiny package using `argparse.ArgumentParser` objects\nto derive a CLI that is automatically applied to a function using type annotations. \n*Currently supports Python 3.10-11*.\n\n### Supported features:\n\n- Argument lists via `nargs=+`\n- Argument choices via `typing.Literal[x, y, z]`\n- Optional values and required arguments\n- Boolean flags via presence or abscence of `--argument_name`\n- Custom parse functions via `@with_argparse(arg_name=custom_fn)`\n- Ignored values: `@with_argparse(ignore_keys={'arg_name'}`\n- Nested type annotations such as `list[int]`\n- Disabled mode: `with_argparse.no_argparse()` context manager\n\nIn order for this package to work, functions must receive an explicit type annotation.\nThe following type annotations are currently supported:\n\n- `str, int, float, bool, ...`\n- Types that have constructors that accept a single `str` as input\n- `list[type]` and `set[type]`\n- `Optional[type], type | None, Union[type, None]`,\n- `Literal[type_val1, type_val2]`\n- Custom types via custom parse functions (supplied via `kwarg` to the `@with_argparse` decorator.\n\n### Example code\n\n```python3\nfrom typing import Optional\nfrom with_argparse import with_argparse\n\ndef custom_parse_fn(inp: str) -> int:\n    return 42 if inp == \"yeah\" else -1\n\n@with_argparse(\n    ignore_keys={\"ignored_value\"}, \n    complex_input=custom_parse_fn\n)\ndef cli(\n    theory_of_everything: int,\n    complex_input: int,\n    ignored_value: Optional[str] = None,\n) -> int:\n    print(ignored_value)\n    return theory_of_everything * complex_input\n\ncli(ignored_value=\"abc\")\n```\n\nwill generate the following CLI output when run:\n\n```text\nusage: --theory_of_everything THEORY_OF_EVERYTHING\n                    [--complex_input COMPLEX_INPUT]\n```\n\n### Custom parse functions\n\nBecomes increasingly useful when the target type `T` does not have a default constructor with a single `str` argument\nor more complex logic is required to parse the desired type from a string input.\n\nAs it is not type correct to use functions as type annotations (it would work extracting those functions from there, \nhowever type checkers such as mypy will complain when doing so), one can specify custom parse functions\ndirectly in the `@with_argparse()` decorator via a keyword argument named as the target parameter.\n\nSay we have a complex function that does call some other functions before eventually returning the string in reverse:\n```python\n\ndef func_a(a: str) -> str: ...\ndef func_b(b: str) -> str: ...\n\ndef custom_fn(inp: str):\n    inp = func_a(inp)\n    inp = func_b(inp)\n    return str(reversed(inp))\n```\n\nOur custom function can also accept types differing from `str`, such as `int`.\n\nWe can then use this function to parse the input the following way in our dummy `cli` function:\n\n```python\n@with_argparse(complex_input=custom_fn)\ndef cli(complex_input: str) -> str:\n    return complex_input\n```\n\n### Boolean values\n\nFor Boolean values, if the default specified is `True`, the CLI argument name is renamed to `--no_argname`,\nsuch that the user must specify to *disable* the given argument. In any other case (`None, False`), the user must\nspecify `--arg_name` to set the Boolean argument to `True`,\n\nThe renaming of a parameter can be disabled by specifying its name in the set `ignore_mapping`, again in the \n`@with_argparse` decorator to the function.\n",
    "bugtrack_url": null,
    "license": "Apache 2.0",
    "summary": "A simple but handy Python library to generate a `argparse.ArgumentParser` object from a type-annotated method",
    "version": "1.0.2",
    "project_urls": {
        "repository": "https://github.com/fleonce/with-argparse/"
    },
    "split_keywords": [
        "argparse",
        " type annotation",
        " auto"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "174df9a8f1c296e251e8d4b1f6250f1dc40e134fad6cd82626463a1130477ea4",
                "md5": "3db7dfecd58ff014bb73ae5c1694a687",
                "sha256": "06d4578e843b6f50dceb6152c33e208225fe8b9ea15428118f11d1861fd8200e"
            },
            "downloads": -1,
            "filename": "with_argparse-1.0.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3db7dfecd58ff014bb73ae5c1694a687",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 14296,
            "upload_time": "2025-01-24T12:44:47",
            "upload_time_iso_8601": "2025-01-24T12:44:47.988403Z",
            "url": "https://files.pythonhosted.org/packages/17/4d/f9a8f1c296e251e8d4b1f6250f1dc40e134fad6cd82626463a1130477ea4/with_argparse-1.0.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a8f983c6ee1eaa0c929bf513b7e024eba923e347ed11a557c03150593d71b3a5",
                "md5": "7a8178f1fc328b93740164fa4a98cc3d",
                "sha256": "9bb4f70fdfa8728b77e07d1a9398966f7cf8d885b64f416626224a2f5480c0c7"
            },
            "downloads": -1,
            "filename": "with_argparse-1.0.2.tar.gz",
            "has_sig": false,
            "md5_digest": "7a8178f1fc328b93740164fa4a98cc3d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 16371,
            "upload_time": "2025-01-24T12:44:49",
            "upload_time_iso_8601": "2025-01-24T12:44:49.809660Z",
            "url": "https://files.pythonhosted.org/packages/a8/f9/83c6ee1eaa0c929bf513b7e024eba923e347ed11a557c03150593d71b3a5/with_argparse-1.0.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-01-24 12:44:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "fleonce",
    "github_project": "with-argparse",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "with-argparse"
}
        
Elapsed time: 0.64655s