<p align="center">
<img src="https://raw.githubusercontent.com/ajatkj/typed_argparser/main/assets/logo.png" width="200" alt="Description of the image">
</p>
<p align="center">
<a href="https://github.com/ajatkj/typed_argparser/actions?query=workflow%3ATest+event%3Apush+branch%3Amain" target="_blank">
<img src="https://img.shields.io/github/actions/workflow/status/ajatkj/typed_argparser/tests.yml?branch=main&event=push&style=flat-square&label=test&color=%2334D058" alt="Test">
</a>
<a href="https://app.codecov.io/gh/ajatkj/typed_argparser/tree/main/" target="_blank">
<img src="https://img.shields.io/codecov/c/github/ajatkj/typed_argparser?color=%2334D058&style=flat-square" alt="Coverage">
</a>
<!-- <a href="https://pypi.org/project/typed-argparser" target="_blank">
<img src="https://img.shields.io/pypi/v/typed-argparser?color=%2334D058&label=pypi%20package&style=flat-square" alt="Package version">
</a>
<a href="https://pypi.org/project/typed-argparser" target="_blank">
<img src="https://img.shields.io/pypi/pyversions/typed-argparser?color=%2334D058&style=flat-square" alt="Supported Python versions">
</a> -->
</p>
# typed-argparser
typed-argparser is a python package to create command line programs by leveraging python type hints.
It uses Python's type hints to provide a convenient way of parsing and validating command line arguments.
## Features
✓ **Type Hinting:** Uses type hints to parse and validate command-line arguments.<br />
✓ **Modular Interface:** Easily define arguments and commands in a clear, organized way.<br />
✓ **Automatic Help Pages:** Generates help pages automatically, so users know how to use your CLI.<br />
✓ **Nested Commands:** Supports complex applications with any level of nested commands.<br />
✓ **File Handling:** Provides out-of-the-box support for handling files.<br />
✓ **Customizable Help Messages:** Fully customizable, giving you control over usage and help messages.<br />
✓ **Built-in Validators:** Comes with many built-in validators, such as time range and length validators.<br />
✓ **Custom Types:** You can define your own custom types to validate and convert command-line arguments.<br />
## Installation
You can install `typed_argparser` using `pip`:
```sh
pip install typed-argparser
```
## Argument Type
All built-in types are supported as argument type annotations. You can also define your own custom types.<br />
Like `argparse`, you can define your own custom types to validate and convert command-line arguments to specific types.<br />
Read more about custom types [here](#Custom-Types).
### Quickstart
| type-hint | nargs | input argument | type |
| ---------------------- | ---------- | ---------------------------------------------------------- | -------------------------- |
| T | - | --opt \<value> | T |
| bool | - | --opt | bool |
| Union[T1, T2, ..., TN] | - | --opt \<value> | T1 \| T2 \| ... \| TN |
| Union[T, bool] | - | --opt | bool |
| | - | --opt \<value> | T |
| List[T] | int, +, \* | --opt \<value>... | [T] |
| | - | --opt \<value1> --opt \<value2>... | [T] |
| Tuple[T1, T2, ..., TN] | N | --opt \<value1> \<value2> ... \<valueN> | (T1, T2, ..., TN) |
| Tuple[T, ...] | N > 2 | --opt \<value1> \<value2>... \<valueN> | (T, ...) |
| Dict[K, V] | - | --opt \<key1=value1> --opt \<key2=value2>... | {K: V} |
| List[Dict[K, V]] | - | --opt \<key1=value1> --opt \<key2=value2>... | [{K: V, ...}] |
| | N > 2 | --opt \<key1=value1> <key3=value3> --opt \<key2=value2>... | [{K: V, ...}, {K: V}, ...] |
| datetime | - | --opt \<value> | datetime |
| date | - | --opt \<value> | date |
| time | - | --opt \<value> | time |
| Path | - | --opt \<value> | Path |
| Url | - | --opt \<value> | Url<sup>\*</sup> |
\* _Url_ is a special type that allows users to provide url as a string. It is not a built-in type but a custom type.
The possibilities are endless but remember some rules:
1. Union types are resolved using the first type that matches the value. So be careful to not use `str` as the first type since everything will match a string.
1. nargs is only applicable for List and Tuple types.
1. List without nargs allows users to use the option multiple times.
1. List with nargs allows users to use multiple values (depending on nargs) for a single option.
1. Dict allows users to use the option multiple times.
1. Dict and List[Dict] behaves similar to each other except that the later supports nargs.
### Arguments to Argument Types (or Runtime Arguments)
Some argument types allow you to pass arguments to them to customize their behavior. <br />
For example, you can pass `mode` to `Path` type to specify the mode in which the file should be opened. <br />
These values are passed using python's `Annotated` type. A special `Args` class is used to pass the arguments to the type.
For example, to pass `mode` to `Path` type, you can use `path: Annotated[Path, Args(mode="r")] = argfield(...)`.
Following tables lists all available arguments to the types.
| type | arguments | description |
| ----------------- | --------------- | -------------------------------------------------------- |
| Path<sup>\*</sup> | mode | mode in which the file should be opened |
| Path<sup>\*</sup> | buffering | buffering for the file |
| Path<sup>\*</sup> | encoding | encoding for the file |
| Path<sup>\*</sup> | errors | errors for the file |
| Path<sup>\*</sup> | newline | newline for the file |
| Date | format | format for the date. defaults to "%Y-%m-%d" |
| DateTime | format | format for the datetime. defaults to "%Y-%m-%dT%H:%M:%S" |
| Time | format | format for the time. defaults to "%H:%M:%S" |
| Url | allowed_schemes | list of allowed schemes for the url |
| Url | host_required | whether the host is required or not |
| Url | port_required | whether the port is required or not |
\* All arguments to pathlib.Path are supported.
Additionally, args from `Annotated` metadata are also automatically supplied to the validators as runtime arguments. <br />
For example, the format argument for datetime type is also supplied to the `DateTimeRangeValidator` validator so that the validator uses the correct format.
## Usage
`examples/example1.py`
```py3
# This is a complete example and should work as is
import os
import sys
from typing import Dict, List, Optional, Tuple, Union
from typed_argparser import ArgumentClass, argfield
class Example1(ArgumentClass):
"""This example shows how to use some of the basic types in typed_argparser."""
# Positional arguments do not generate short or long options
opt1: Union[int, str] = argfield(help="opt1 is a mandatory argument which can be an integer or a string")
opt2: List[str] = argfield(help="opt2 is a mandatory argument and can be used multiple times")
# Optional arguments generate only long option by default if no short option is provided
opt3: Optional[str] = argfield(help="this is an optional argument.")
# Use Dict type to accept multiple key value pairs
opt4: Optional[Dict[str, int]] = argfield(help="accept key value pairs. can be used multiple times.")
# Use Tuple type to accept exactly n no. of arguments
opt5: Optional[Tuple[str, ...]] = argfield("-o", "--option5", nargs=4, help="accept multiple options")
cli = Example1()
"""
usage: example1 [--opt3 <value>] [--opt4 <key=value>] [-o <value1> <value2> <value3> <value4>] [--help]
<opt1> <opt2>
description:
This example shows how to use some of the basic types in typed_argparser.
positional:
<opt1> opt1 is a mandatory argument which can be an integer or a string [(int|str)]
<opt2> opt2 is a mandatory argument and can be used multiple times [str]
(multiple allowed)
options:
--opt3 <value> this is an optional argument. [str]
--opt4 <key=value> accept key value pairs. can be used multiple times. [str, int]
(multiple allowed)
-o, --option5 <value1> <value2> <value3> <value4> accept multiple options [(str,...)]
miscellaneous:
--help show this help message and exit
"""
cli.parse("--opt4 abc=10 --opt4 xyz=20 --option5 a b c d 20 abc")
"""
ParsedExample1(opt1=20, opt2=['abc'], opt3=None, opt4={'abc': 10, 'xyz': 20}, opt5=('a', 'b', 'c', 'd'))
"""
print(cli)
```
Check `examples` directory for more examples. For more complex examples, check `git_cli` example.
## API Reference
This section provides an overview of the API and classes used in typed_argparser.
### ArgumentClass
`ArgumentClass` is the main class in `typed_argparser`. <br />
It is used to define the command line interface and defines how the arguments are parsed.<br />
To use `ArgumentClass`, you need to define a subclass of it and define the arguments using the `argfield` function.
#### Class Variables
All class variables are optional and can be used to customize the CLI program.
- **\_\_program\_\_**: The name of the CLI program.
- **\_\_description\_\_**:The description of the CLI program.
- **\_\_epilog\_\_**: The epilog of the CLI program.
- **\_\_usage\_\_**: The usage message of the CLI program.
- **\_\_version\_\_**: The version of the CLI program.
```py3
class CLI(ArgumentClass):
__program__ = "ls"
__description__ = "Lists the files in a directory."
__version__ = "1.0.0"
long_format: Optional[bool] = argfield("-l", "--long", help="List files in long format.")
recursive: Optional[bool] = argfield("-r", "--recursive", help="List files recursively.")
directory: List[str] = argfield("-d", nargs="+", help="Directory to list files in.")
```
#### Methods
- ArgumentClass.parse(args: None)<br />
Parses the command line arguments and updates the class attributes.
- ArgumentClass.execute(immediately = True, open_files = True)<br />
Decorator to execute a function when all positional arguments of the function are provided via CLI arguments.
### ArgumentConfig
`ArgumentConfig` is a class that holds the configuration for the `ArgumentClass`. Pass this object to the `ArgumentClass` constructor to customize the CLI program.
#### Parameters
- **show_default_in_help** (bool): Whether to show default values in help messages. Defaults to True.
- **show_none_default** (bool): Whether to show default values even if they are None. Defaults to False.
- **show_type_in_help** (bool): Whether to show argument types in help messages. Defaults to True.
- **metavar_transform** (Callable[[str], str]): Function for transforming metavar strings. This is applied after all sources of metavar have been resolved.
- **heading_transform** (Callable[[str], str]): Function for transforming heading strings.
- **add_help** (bool): Whether to include help option in the parser. Defaults to True.
- **groups_sort_order** (List[str] | None): Order in which argument groups should be sorted in help message. <br />`
"\*" is a wildcard which signifies all groups. Defaults to ["positional", "optional", "\*", "commands", "miscellaneous"].<br />
Note: names should be an exact match to the headings.
- **compact_usage** (bool): Whether to use compact usage message. Defaults to False.<br />
Note: You can use `command_metavar` and `option_metavar` to change the metavar for commands and optional arguments respectively.
- **default_options_group_heading** (str): Default heading for options groups. Defaults to "options".<br />
Note: `heading_transform` will be applied to this parameter.
- **default_positional_group_heading** (str): Default heading for positional groups. Defaults to "positional".<br />
Note: `heading_transform` will be applied to this parameter
- **default_commands_group_heading** (str): Default heading for commands groups. Defaults to "commands".<br />
Note: `heading_transform` will be applied to this parameter
- **default_miscellaneous_group_heading** (str): Default heading for miscellaneous groups. Defaults to "miscellaneous".<br />
Note: `heading_transform` will be applied to this parameter
- **default_description_heading** (str | None): Default heading for descriptions. Defaults to "description". Set this to `None`
to hide the description heading.<br />
Note: `heading_transform` will be applied to this parameter
- **default_usage_prefix** (str): Default prefix for usage messages. Defaults to "usage: ".<br />
Note: this value will be used as is without any transformation
- **command_metavar** (str): Metavar string for commands. Defaults to "commmand". <br />
Note: `command_metavar` is used for both `compact_usage` and default usage generated by `ArgumentClass`. Metavar transformation `transform_metavar` is only applied for default usage. For `compact_usage`, the value is used as is.
- **option_metavar** (str): Metavar string for options. Defaults to "option".<br />
Note: no transformation is applied to this value.
- **extra_arguments** (Literal["allow", "ignore", "error"]): Behavior for handling extra arguments. Defaults to "error".<br />
When set to `allow` a new property `extra_fields` is added to the instance of `ArgumentClass`.
- **allow_multiple_commands** (bool) _(experimental)_: Allow multiple commands. Defaults to False.
### argfield
Returns an `ArgumentField` object, which represents an argument in the command line interface.
#### Function Arguments
- **default** (T | None): The default value for the argument. It must of the same type as the argument (defined by the type hint).
- **nargs** (int | Literal["*", "+", "?"] | None): The number of times the argument can be provided.
- **const** (T | None): A constant value for the argument. It must of the same type as the argument (defined by the type hint).
- **dest** (str | None): Specify the name of the class attribute to which the argument is assigned. Specifically used to assign multiple arguments to a single class attribute using `const`.
- **metavar** (str | None): Alternate display name for the argument in the help message.
- **aliases** (Set[str] | None): A list of alternative names for a command (not applicable for arguments).
- **validator** (ArgumentValidator | None): An optional validator for the argument. Read more about validators [here](#Validators).
- **counter** (bool | None): Whether the argument is a counter. This is used to count the number of times an argument is provided (ex. -vvv).
- **help** (str | None): A help message for the argument. Set to `SUPPRESS` to hide the argument in the help message.
### ArgumentGroup
`ArgumentGroup` is a class that represents a group of arguments in the command line interface. It is used to organize arguments into logical sections. <br />
To define a group, you need to create a subclass of `ArgumentGroup` and define the arguments using the `argfield` function.
#### Class Variables
- **\_\_title\_\_** (str): The title of the group.
- **\_\_group_description\_\_** (str | None): An optional description of the group.
- **\_\_hide_title\_\_** (bool): Whether to hide the title of the group in the help message.
- **\_\_exclusive\_\_** (bool): If set to True, only one argument in the group can be provided at a time.
- **\_\_required\_\_** (bool): If set to True, at least one argument in the mutually exclusive group must be provided.
### Validators
Validators provide easy way to validate your arguments as soon as they are parsed. `typed_argparser` provides certain
built-in validators but you can as easily implement your own validators (check [Custom Validators](#Custom-Validators)).
1. #### LengthValidator
Validates if the argument is of the specified length.<br />
Parameters:
- **min** (int | None): Minimum length of the argument.
- **max** (int | None): Maximum length of the argument.
1. #### RangeValidator
Validates if a numeric argument is within the specified range.<br />
Parameters:
- **min** (int | float | None): Minimum value of the argument.
- **max** (int | float | None): Maximum value of the argument.
1. #### DateTimeRangeValidator
Validates if the argument is within the specified date, time or datetime range.<br />
Parameters:
- **min** (str | None): Minimum value of datetime argument.
- **max** (str | None): Maximum value of datetime argument.
- **format** (str | None): Datetime format. Defaults to "%Y-%m-%d" for date, "%H:%M:%S" for time and "%Y-%m-%dT%H:%M:%S" for datetime.
1. #### PathValidator
Validates if the argument is a valid path.<br />
Parameters:
- **is_absolute** (bool | None): Whether the path is absolute or not.
- **is_dir** (bool | None): Whether the path is a directory or not.
- **is_file** (bool | None): Whether the path is a file or not.
- **exists** (bool | None): Whether the path exists or not.
1. #### UrlValidator
Validates if the argument is a valid url.<br />
Parameters:
- **allowed_schemes** (List[str] | None): List of allowed schemes for the url.
- **host_required** (bool | None): Whether the host is required or not.
- **port_required** (bool | None): Whether the port is required or not.
1. #### RegexValidator
Validates the argument against a regex pattern.<br />
Parameters:
- **pattern** (str | None): Regex pattern to validate the argument.
1. #### ConfirmationValidator
This is a special validator that asks for confirmation before proceeding with the execution of the program.<br />
If the answer does not match any of the answers provided, the program will exit with an error.<br />
Parameters:
- **message** (str | None): Message to display before asking for confirmation.
- **abort_message** (str | None): Message to display when confirmation is aborted.
- **answers** (List[str] | None): List of answers to accepted for confirmation.
- **ignore_case** (bool | None): Whether to ignore case when comparing answers. Defaults to True.
## Commands
Defining commands in `typed_argparser` is similar to defining arguments.<br />
You can create a subclass of `ArgumentClass` and define the arguments using the `argfield` function. Then use the command class as typehint for the command argument.
```py3
class InitCommand(ArgumentClass):
quiet: Optional[bool] = argfield(
"-q", help="Only print error and warning messages; all other output will be suppressed."
)
branch: Optional[Path]= argfield("--initial-branch", "-b", help="Use the specified name for the initial branch in the newly created repository.")
class Git(ArgumentClass):
init: InitCommand = argfield(help="Initialize a new Git repository.")
```
## Advanced
### Custom Types
To be updated soon.
```py3
```
### Custom Validators
To define a custom validator, you need to create a subclass of `ArgumentValidator` and define 2 methods: `__init__` and `validator`. <br />
`__init__` accepts the validator arguments as keyword arguments and is used to initialize the validator. <br />
`validator` accepts the value to be validated as a parameter and is used to validate the value. Any runtime arguments are passed to the validator as keyword arguments.
Simple example of a custom validator that validates if a numnber is within a range:
```py3
class MyValidator(ArgumentValidator):
def __init__(self, min: Optional[int] = None, max: Optional[int] = None) -> None:
if (min and max and min >= max) or (min is None and max is None):
raise ValidatorInitError("invalid range provided", validator=self)
self.min = min
self.max = max
def validator(self, value: str) -> None:
if self.min and self.max and (len(value) < self.min or len(value) > self.max):
raise ValidationError(f"string length should be between {self.min} and {self.max}", validator=self)
if self.min and len(value) < self.min:
raise ValidationError(f"string length should be greater than {self.min}", validator=self)
if self.max and len(value) > self.max:
raise ValidationError(f"string length should be less than {self.max}", validator=self)
```
# License
[MIT License](./LICENSE)
# Contribution
If you are interested in contributing to typed_argparser, please take a look at the [contributing guidelines](./CONTRIBUTING.md).
Raw data
{
"_id": null,
"home_page": null,
"name": "typed-argparser",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "typed, argparse, argparser, argparse-typed",
"author": null,
"author_email": "Ankit Jain <ajatkj.dev@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/e2/bf/cf992c97b143a781477f77dbfd50e85435387829872fef815fb2fc7597b8/typed_argparser-1.0.0.post3.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/ajatkj/typed_argparser/main/assets/logo.png\" width=\"200\" alt=\"Description of the image\">\n</p>\n<p align=\"center\">\n <a href=\"https://github.com/ajatkj/typed_argparser/actions?query=workflow%3ATest+event%3Apush+branch%3Amain\" target=\"_blank\">\n <img src=\"https://img.shields.io/github/actions/workflow/status/ajatkj/typed_argparser/tests.yml?branch=main&event=push&style=flat-square&label=test&color=%2334D058\" alt=\"Test\">\n </a>\n <a href=\"https://app.codecov.io/gh/ajatkj/typed_argparser/tree/main/\" target=\"_blank\">\n <img src=\"https://img.shields.io/codecov/c/github/ajatkj/typed_argparser?color=%2334D058&style=flat-square\" alt=\"Coverage\">\n </a>\n <!-- <a href=\"https://pypi.org/project/typed-argparser\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/v/typed-argparser?color=%2334D058&label=pypi%20package&style=flat-square\" alt=\"Package version\">\n </a>\n <a href=\"https://pypi.org/project/typed-argparser\" target=\"_blank\">\n <img src=\"https://img.shields.io/pypi/pyversions/typed-argparser?color=%2334D058&style=flat-square\" alt=\"Supported Python versions\">\n </a> -->\n</p>\n\n# typed-argparser\n\ntyped-argparser is a python package to create command line programs by leveraging python type hints.\nIt uses Python's type hints to provide a convenient way of parsing and validating command line arguments.\n\n## Features\n\n\u2713 **Type Hinting:** Uses type hints to parse and validate command-line arguments.<br />\n\u2713 **Modular Interface:** Easily define arguments and commands in a clear, organized way.<br />\n\u2713 **Automatic Help Pages:** Generates help pages automatically, so users know how to use your CLI.<br />\n\u2713 **Nested Commands:** Supports complex applications with any level of nested commands.<br />\n\u2713 **File Handling:** Provides out-of-the-box support for handling files.<br />\n\u2713 **Customizable Help Messages:** Fully customizable, giving you control over usage and help messages.<br />\n\u2713 **Built-in Validators:** Comes with many built-in validators, such as time range and length validators.<br />\n\u2713 **Custom Types:** You can define your own custom types to validate and convert command-line arguments.<br />\n\n## Installation\n\nYou can install `typed_argparser` using `pip`:\n\n```sh\npip install typed-argparser\n```\n\n## Argument Type\n\nAll built-in types are supported as argument type annotations. You can also define your own custom types.<br />\nLike `argparse`, you can define your own custom types to validate and convert command-line arguments to specific types.<br />\nRead more about custom types [here](#Custom-Types).\n\n### Quickstart\n\n| type-hint | nargs | input argument | type |\n| ---------------------- | ---------- | ---------------------------------------------------------- | -------------------------- |\n| T | - | --opt \\<value> | T |\n| bool | - | --opt | bool |\n| Union[T1, T2, ..., TN] | - | --opt \\<value> | T1 \\| T2 \\| ... \\| TN |\n| Union[T, bool] | - | --opt | bool |\n| | - | --opt \\<value> | T |\n| List[T] | int, +, \\* | --opt \\<value>... | [T] |\n| | - | --opt \\<value1> --opt \\<value2>... | [T] |\n| Tuple[T1, T2, ..., TN] | N | --opt \\<value1> \\<value2> ... \\<valueN> | (T1, T2, ..., TN) |\n| Tuple[T, ...] | N > 2 | --opt \\<value1> \\<value2>... \\<valueN> | (T, ...) |\n| Dict[K, V] | - | --opt \\<key1=value1> --opt \\<key2=value2>... | {K: V} |\n| List[Dict[K, V]] | - | --opt \\<key1=value1> --opt \\<key2=value2>... | [{K: V, ...}] |\n| | N > 2 | --opt \\<key1=value1> <key3=value3> --opt \\<key2=value2>... | [{K: V, ...}, {K: V}, ...] |\n| datetime | - | --opt \\<value> | datetime |\n| date | - | --opt \\<value> | date |\n| time | - | --opt \\<value> | time |\n| Path | - | --opt \\<value> | Path |\n| Url | - | --opt \\<value> | Url<sup>\\*</sup> |\n\n\\* _Url_ is a special type that allows users to provide url as a string. It is not a built-in type but a custom type.\n\nThe possibilities are endless but remember some rules:\n\n1. Union types are resolved using the first type that matches the value. So be careful to not use `str` as the first type since everything will match a string.\n1. nargs is only applicable for List and Tuple types.\n1. List without nargs allows users to use the option multiple times.\n1. List with nargs allows users to use multiple values (depending on nargs) for a single option.\n1. Dict allows users to use the option multiple times.\n1. Dict and List[Dict] behaves similar to each other except that the later supports nargs.\n\n### Arguments to Argument Types (or Runtime Arguments)\n\nSome argument types allow you to pass arguments to them to customize their behavior. <br />\nFor example, you can pass `mode` to `Path` type to specify the mode in which the file should be opened. <br />\nThese values are passed using python's `Annotated` type. A special `Args` class is used to pass the arguments to the type.\nFor example, to pass `mode` to `Path` type, you can use `path: Annotated[Path, Args(mode=\"r\")] = argfield(...)`.\n\nFollowing tables lists all available arguments to the types.\n\n| type | arguments | description |\n| ----------------- | --------------- | -------------------------------------------------------- |\n| Path<sup>\\*</sup> | mode | mode in which the file should be opened |\n| Path<sup>\\*</sup> | buffering | buffering for the file |\n| Path<sup>\\*</sup> | encoding | encoding for the file |\n| Path<sup>\\*</sup> | errors | errors for the file |\n| Path<sup>\\*</sup> | newline | newline for the file |\n| Date | format | format for the date. defaults to \"%Y-%m-%d\" |\n| DateTime | format | format for the datetime. defaults to \"%Y-%m-%dT%H:%M:%S\" |\n| Time | format | format for the time. defaults to \"%H:%M:%S\" |\n| Url | allowed_schemes | list of allowed schemes for the url |\n| Url | host_required | whether the host is required or not |\n| Url | port_required | whether the port is required or not |\n\n\\* All arguments to pathlib.Path are supported.\n\nAdditionally, args from `Annotated` metadata are also automatically supplied to the validators as runtime arguments. <br />\nFor example, the format argument for datetime type is also supplied to the `DateTimeRangeValidator` validator so that the validator uses the correct format.\n\n## Usage\n\n`examples/example1.py`\n\n```py3\n# This is a complete example and should work as is\n\nimport os\nimport sys\nfrom typing import Dict, List, Optional, Tuple, Union\n\nfrom typed_argparser import ArgumentClass, argfield\n\n\nclass Example1(ArgumentClass):\n \"\"\"This example shows how to use some of the basic types in typed_argparser.\"\"\"\n\n # Positional arguments do not generate short or long options\n opt1: Union[int, str] = argfield(help=\"opt1 is a mandatory argument which can be an integer or a string\")\n opt2: List[str] = argfield(help=\"opt2 is a mandatory argument and can be used multiple times\")\n # Optional arguments generate only long option by default if no short option is provided\n opt3: Optional[str] = argfield(help=\"this is an optional argument.\")\n # Use Dict type to accept multiple key value pairs\n opt4: Optional[Dict[str, int]] = argfield(help=\"accept key value pairs. can be used multiple times.\")\n # Use Tuple type to accept exactly n no. of arguments\n opt5: Optional[Tuple[str, ...]] = argfield(\"-o\", \"--option5\", nargs=4, help=\"accept multiple options\")\n\n\ncli = Example1()\n\n\"\"\"\nusage: example1 [--opt3 <value>] [--opt4 <key=value>] [-o <value1> <value2> <value3> <value4>] [--help]\n <opt1> <opt2>\n\ndescription:\nThis example shows how to use some of the basic types in typed_argparser.\n\npositional:\n<opt1> opt1 is a mandatory argument which can be an integer or a string [(int|str)]\n<opt2> opt2 is a mandatory argument and can be used multiple times [str]\n (multiple allowed)\n\noptions:\n --opt3 <value> this is an optional argument. [str]\n --opt4 <key=value> accept key value pairs. can be used multiple times. [str, int]\n (multiple allowed)\n-o, --option5 <value1> <value2> <value3> <value4> accept multiple options [(str,...)]\n\nmiscellaneous:\n --help show this help message and exit\n\"\"\"\n\ncli.parse(\"--opt4 abc=10 --opt4 xyz=20 --option5 a b c d 20 abc\")\n\n\"\"\"\nParsedExample1(opt1=20, opt2=['abc'], opt3=None, opt4={'abc': 10, 'xyz': 20}, opt5=('a', 'b', 'c', 'd'))\n\"\"\"\nprint(cli)\n\n```\n\nCheck `examples` directory for more examples. For more complex examples, check `git_cli` example.\n\n## API Reference\n\nThis section provides an overview of the API and classes used in typed_argparser.\n\n### ArgumentClass\n\n`ArgumentClass` is the main class in `typed_argparser`. <br />\nIt is used to define the command line interface and defines how the arguments are parsed.<br />\nTo use `ArgumentClass`, you need to define a subclass of it and define the arguments using the `argfield` function.\n\n#### Class Variables\n\nAll class variables are optional and can be used to customize the CLI program.\n\n- **\\_\\_program\\_\\_**: The name of the CLI program.\n- **\\_\\_description\\_\\_**:The description of the CLI program.\n- **\\_\\_epilog\\_\\_**: The epilog of the CLI program.\n- **\\_\\_usage\\_\\_**: The usage message of the CLI program.\n- **\\_\\_version\\_\\_**: The version of the CLI program.\n\n```py3\nclass CLI(ArgumentClass):\n __program__ = \"ls\"\n __description__ = \"Lists the files in a directory.\"\n __version__ = \"1.0.0\"\n\n long_format: Optional[bool] = argfield(\"-l\", \"--long\", help=\"List files in long format.\")\n recursive: Optional[bool] = argfield(\"-r\", \"--recursive\", help=\"List files recursively.\")\n directory: List[str] = argfield(\"-d\", nargs=\"+\", help=\"Directory to list files in.\")\n```\n\n#### Methods\n\n- ArgumentClass.parse(args: None)<br />\n Parses the command line arguments and updates the class attributes.\n\n- ArgumentClass.execute(immediately = True, open_files = True)<br />\n Decorator to execute a function when all positional arguments of the function are provided via CLI arguments.\n\n### ArgumentConfig\n\n`ArgumentConfig` is a class that holds the configuration for the `ArgumentClass`. Pass this object to the `ArgumentClass` constructor to customize the CLI program.\n\n#### Parameters\n\n- **show_default_in_help** (bool): Whether to show default values in help messages. Defaults to True.\n- **show_none_default** (bool): Whether to show default values even if they are None. Defaults to False.\n- **show_type_in_help** (bool): Whether to show argument types in help messages. Defaults to True.\n- **metavar_transform** (Callable[[str], str]): Function for transforming metavar strings. This is applied after all sources of metavar have been resolved.\n- **heading_transform** (Callable[[str], str]): Function for transforming heading strings.\n- **add_help** (bool): Whether to include help option in the parser. Defaults to True.\n- **groups_sort_order** (List[str] | None): Order in which argument groups should be sorted in help message. <br />`\n \"\\*\" is a wildcard which signifies all groups. Defaults to [\"positional\", \"optional\", \"\\*\", \"commands\", \"miscellaneous\"].<br />\n Note: names should be an exact match to the headings.\n- **compact_usage** (bool): Whether to use compact usage message. Defaults to False.<br />\n Note: You can use `command_metavar` and `option_metavar` to change the metavar for commands and optional arguments respectively.\n- **default_options_group_heading** (str): Default heading for options groups. Defaults to \"options\".<br />\n Note: `heading_transform` will be applied to this parameter.\n- **default_positional_group_heading** (str): Default heading for positional groups. Defaults to \"positional\".<br />\n Note: `heading_transform` will be applied to this parameter\n- **default_commands_group_heading** (str): Default heading for commands groups. Defaults to \"commands\".<br />\n Note: `heading_transform` will be applied to this parameter\n- **default_miscellaneous_group_heading** (str): Default heading for miscellaneous groups. Defaults to \"miscellaneous\".<br />\n Note: `heading_transform` will be applied to this parameter\n- **default_description_heading** (str | None): Default heading for descriptions. Defaults to \"description\". Set this to `None`\n to hide the description heading.<br />\n Note: `heading_transform` will be applied to this parameter\n- **default_usage_prefix** (str): Default prefix for usage messages. Defaults to \"usage: \".<br />\n Note: this value will be used as is without any transformation\n- **command_metavar** (str): Metavar string for commands. Defaults to \"commmand\". <br />\n Note: `command_metavar` is used for both `compact_usage` and default usage generated by `ArgumentClass`. Metavar transformation `transform_metavar` is only applied for default usage. For `compact_usage`, the value is used as is.\n- **option_metavar** (str): Metavar string for options. Defaults to \"option\".<br />\n Note: no transformation is applied to this value.\n- **extra_arguments** (Literal[\"allow\", \"ignore\", \"error\"]): Behavior for handling extra arguments. Defaults to \"error\".<br />\n When set to `allow` a new property `extra_fields` is added to the instance of `ArgumentClass`.\n- **allow_multiple_commands** (bool) _(experimental)_: Allow multiple commands. Defaults to False.\n\n### argfield\n\nReturns an `ArgumentField` object, which represents an argument in the command line interface.\n\n#### Function Arguments\n\n- **default** (T | None): The default value for the argument. It must of the same type as the argument (defined by the type hint).\n- **nargs** (int | Literal[\"*\", \"+\", \"?\"] | None): The number of times the argument can be provided.\n- **const** (T | None): A constant value for the argument. It must of the same type as the argument (defined by the type hint).\n- **dest** (str | None): Specify the name of the class attribute to which the argument is assigned. Specifically used to assign multiple arguments to a single class attribute using `const`.\n- **metavar** (str | None): Alternate display name for the argument in the help message.\n- **aliases** (Set[str] | None): A list of alternative names for a command (not applicable for arguments).\n- **validator** (ArgumentValidator | None): An optional validator for the argument. Read more about validators [here](#Validators).\n- **counter** (bool | None): Whether the argument is a counter. This is used to count the number of times an argument is provided (ex. -vvv).\n- **help** (str | None): A help message for the argument. Set to `SUPPRESS` to hide the argument in the help message.\n\n### ArgumentGroup\n\n`ArgumentGroup` is a class that represents a group of arguments in the command line interface. It is used to organize arguments into logical sections. <br />\nTo define a group, you need to create a subclass of `ArgumentGroup` and define the arguments using the `argfield` function.\n\n#### Class Variables\n\n- **\\_\\_title\\_\\_** (str): The title of the group.\n- **\\_\\_group_description\\_\\_** (str | None): An optional description of the group.\n- **\\_\\_hide_title\\_\\_** (bool): Whether to hide the title of the group in the help message.\n- **\\_\\_exclusive\\_\\_** (bool): If set to True, only one argument in the group can be provided at a time.\n- **\\_\\_required\\_\\_** (bool): If set to True, at least one argument in the mutually exclusive group must be provided.\n\n### Validators\n\nValidators provide easy way to validate your arguments as soon as they are parsed. `typed_argparser` provides certain\nbuilt-in validators but you can as easily implement your own validators (check [Custom Validators](#Custom-Validators)).\n\n1. #### LengthValidator\n\n Validates if the argument is of the specified length.<br />\n Parameters:\n\n - **min** (int | None): Minimum length of the argument.\n - **max** (int | None): Maximum length of the argument.\n\n1. #### RangeValidator\n\n Validates if a numeric argument is within the specified range.<br />\n Parameters:\n\n - **min** (int | float | None): Minimum value of the argument.\n - **max** (int | float | None): Maximum value of the argument.\n\n1. #### DateTimeRangeValidator\n\n Validates if the argument is within the specified date, time or datetime range.<br />\n Parameters:\n\n - **min** (str | None): Minimum value of datetime argument.\n - **max** (str | None): Maximum value of datetime argument.\n - **format** (str | None): Datetime format. Defaults to \"%Y-%m-%d\" for date, \"%H:%M:%S\" for time and \"%Y-%m-%dT%H:%M:%S\" for datetime.\n\n1. #### PathValidator\n\n Validates if the argument is a valid path.<br />\n Parameters:\n\n - **is_absolute** (bool | None): Whether the path is absolute or not.\n - **is_dir** (bool | None): Whether the path is a directory or not.\n - **is_file** (bool | None): Whether the path is a file or not.\n - **exists** (bool | None): Whether the path exists or not.\n\n1. #### UrlValidator\n\n Validates if the argument is a valid url.<br />\n Parameters:\n\n - **allowed_schemes** (List[str] | None): List of allowed schemes for the url.\n - **host_required** (bool | None): Whether the host is required or not.\n - **port_required** (bool | None): Whether the port is required or not.\n\n1. #### RegexValidator\n\n Validates the argument against a regex pattern.<br />\n Parameters:\n\n - **pattern** (str | None): Regex pattern to validate the argument.\n\n1. #### ConfirmationValidator\n\n This is a special validator that asks for confirmation before proceeding with the execution of the program.<br />\n If the answer does not match any of the answers provided, the program will exit with an error.<br />\n Parameters:\n\n - **message** (str | None): Message to display before asking for confirmation.\n - **abort_message** (str | None): Message to display when confirmation is aborted.\n - **answers** (List[str] | None): List of answers to accepted for confirmation.\n - **ignore_case** (bool | None): Whether to ignore case when comparing answers. Defaults to True.\n\n## Commands\n\nDefining commands in `typed_argparser` is similar to defining arguments.<br />\nYou can create a subclass of `ArgumentClass` and define the arguments using the `argfield` function. Then use the command class as typehint for the command argument.\n\n```py3\nclass InitCommand(ArgumentClass):\n quiet: Optional[bool] = argfield(\n \"-q\", help=\"Only print error and warning messages; all other output will be suppressed.\"\n )\n branch: Optional[Path]= argfield(\"--initial-branch\", \"-b\", help=\"Use the specified name for the initial branch in the newly created repository.\")\n\nclass Git(ArgumentClass):\n init: InitCommand = argfield(help=\"Initialize a new Git repository.\")\n```\n\n## Advanced\n\n### Custom Types\n\nTo be updated soon.\n\n```py3\n\n```\n\n### Custom Validators\n\nTo define a custom validator, you need to create a subclass of `ArgumentValidator` and define 2 methods: `__init__` and `validator`. <br />\n`__init__` accepts the validator arguments as keyword arguments and is used to initialize the validator. <br />\n`validator` accepts the value to be validated as a parameter and is used to validate the value. Any runtime arguments are passed to the validator as keyword arguments.\n\nSimple example of a custom validator that validates if a numnber is within a range:\n\n```py3\nclass MyValidator(ArgumentValidator):\n def __init__(self, min: Optional[int] = None, max: Optional[int] = None) -> None:\n if (min and max and min >= max) or (min is None and max is None):\n raise ValidatorInitError(\"invalid range provided\", validator=self)\n self.min = min\n self.max = max\n\n def validator(self, value: str) -> None:\n if self.min and self.max and (len(value) < self.min or len(value) > self.max):\n raise ValidationError(f\"string length should be between {self.min} and {self.max}\", validator=self)\n if self.min and len(value) < self.min:\n raise ValidationError(f\"string length should be greater than {self.min}\", validator=self)\n if self.max and len(value) > self.max:\n raise ValidationError(f\"string length should be less than {self.max}\", validator=self)\n\n```\n\n# License\n\n[MIT License](./LICENSE)\n\n# Contribution\n\nIf you are interested in contributing to typed_argparser, please take a look at the [contributing guidelines](./CONTRIBUTING.md).\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Simplify command line argument parsing & validation with type hints",
"version": "1.0.0.post3",
"project_urls": {
"Repository": "https://github.com/ajatkj/typed_argparser"
},
"split_keywords": [
"typed",
" argparse",
" argparser",
" argparse-typed"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "18667683f5f4358a74c25e05d39ae9993f2646a2503e4c16274a2e33a61f5c1e",
"md5": "b94d96f268cb3ee9a4d779d850b2f746",
"sha256": "61910e5d433a988a6a5bd24de6292c9dd700e8125dedec1ed0eb1e91cc172081"
},
"downloads": -1,
"filename": "typed_argparser-1.0.0.post3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b94d96f268cb3ee9a4d779d850b2f746",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 70933,
"upload_time": "2024-07-08T12:24:25",
"upload_time_iso_8601": "2024-07-08T12:24:25.943156Z",
"url": "https://files.pythonhosted.org/packages/18/66/7683f5f4358a74c25e05d39ae9993f2646a2503e4c16274a2e33a61f5c1e/typed_argparser-1.0.0.post3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e2bfcf992c97b143a781477f77dbfd50e85435387829872fef815fb2fc7597b8",
"md5": "7483bbef8738c55a7fd56644d1aab3e4",
"sha256": "80df20539f91402569f86f924b57c7004c64f8132ecd5b4079e8b0d3edf8f7d6"
},
"downloads": -1,
"filename": "typed_argparser-1.0.0.post3.tar.gz",
"has_sig": false,
"md5_digest": "7483bbef8738c55a7fd56644d1aab3e4",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 95778,
"upload_time": "2024-07-08T12:24:27",
"upload_time_iso_8601": "2024-07-08T12:24:27.585152Z",
"url": "https://files.pythonhosted.org/packages/e2/bf/cf992c97b143a781477f77dbfd50e85435387829872fef815fb2fc7597b8/typed_argparser-1.0.0.post3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-08 12:24:27",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ajatkj",
"github_project": "typed_argparser",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "typed-argparser"
}