# Argparse Type Helper
A lightweight helper that lets you leverage type hints with `argparse`.
## Installation
```bash
pip install argparse-type-helper
```
## Features
- **Class-based schema**
Bundle all your arguments in a single `@targs`-decorated class.
- **Identical API**
Each field uses the same parameters as `argparse.add_argument` (`help`, `action`, `nargs`, etc.).
- **Automatic registration**
One call to `register_targs(parser, YourArgs)` wires up all arguments on your `ArgumentParser`.
- **Typed extraction**
After `parse_args()`, call `extract_targs()` to get a fully-typed instance of your class.
- **Hybrid usage**
Mix native `parser.add_argument(...)` calls with class-based definitions in the same parser.
- **Docstring support**
Use docstrings to automatically generate help text for your arguments.
## Why not [typed-argparse](https://typed-argparse.github.io/typed-argparse/)?
typed-argparse is a great library, but it replaces the familiar `argparse.add_argument` API with its own argument-definition interface, which can be a hurdle when integrating into an existing codebase.
argparse-type-helper, by contrast, is a simple helper that allows you to use type hints with argparse with minimal learning curve. It uses the same `argparse` API you’re already familiar with, and you can even mix native `argparse` usage with class-based definitions in the same parser.
## Usage
<!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./tests/example.py) -->
<!-- The below code snippet is automatically added from ./tests/example.py -->
```py
import argparse
import sys
from typing import Never
from argparse_type_helper import (
Flag,
Name,
extract_targs,
post_init,
register_targs,
targ,
targs,
)
# Define your typed arguments as a targ class
@targs
class MyArgs:
# This example will show the common usage of targ.
positional: str = targ(Name, help="A positional argument (positional).")
custom_name_pos: str = targ(
"my_positional", help="A custom named positional argument."
)
optional: str = targ(Flag, help="An optional argument (--optional).")
optional_dash: str = targ(
Flag, help="underscore is replaced with dash (--optional-dash)."
)
optional_short: str = targ(
Flag("-s"), help="You can also add a short name (-s, --optional-short)."
)
custom_name_opt: str = targ(
"--my-optional",
help="A custom named optional argument.",
)
custom_name_opt_short: str = targ(
("-c", "--my-short-optional"),
help="A custom named optional argument with a short name. (note the tuple)",
)
options: list[str] = targ(
Flag,
action="extend",
nargs="+",
default=[],
help="All options (`help`, `action`, `nargs`, etc.) are the same as argparse.",
)
choices: str = targ(
Flag,
choices=["option1", "option2", "option3"],
help="Another example argument with choices.",
)
flag: bool = targ(
Flag("-d"), action="store_true", help="Another example boolean flag."
)
default_type: int = targ(
Flag,
default=42,
help="if type is not specified, it defaults to the type hint. (type=int in this case)",
)
custom_type: float = targ(
Flag,
type=lambda x: round(float(x), 1),
default=3.14,
help="You can also specify a custom type",
)
docstring_as_help: str = targ(Flag, default="default value")
"""
If you don't specify a help, it will use the docstring as the help text.
This is useful for documentation purposes.
Your LSP will also pick this up.
"""
# You can also use the `post_init` decorator to execute some code after the arguments are extracted.
# This is useful for validation or other post-processing.
@post_init
def validate(self) -> None:
if self.positional == "error":
raise ValueError("positional argument cannot be 'error'")
# You can register the targs with a custom parser
class MyParser(argparse.ArgumentParser):
def error(self, message: str) -> Never:
sys.stderr.write("error: %s\n" % message)
self.print_help()
sys.exit(2)
if __name__ == "__main__":
# Create a parser
parser = MyParser(description="Process some data arguments.")
# Register the targs with the parser
# verbose=True will print the registered arguments
register_targs(parser, MyArgs, verbose=True)
# Hybrid usage example
parser.add_argument("--version", action="version", version="MyArgs 1.0.0")
# Parse the arguments
args = parser.parse_args()
# Extract the targs from the parsed arguments
my_args = extract_targs(args, MyArgs)
print(f"Parsed arguments: {my_args}")
```
<!-- MARKDOWN-AUTO-DOCS:END -->
Raw data
{
"_id": null,
"home_page": null,
"name": "argparse-type-helper",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "argparse, typing, argument parser, type hints, typed arguments",
"author": null,
"author_email": "lljbash <lljbash@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/68/c6/cdd65cb29306ff4e79966b0cf70a21bb727f88c70111b3ea020fb4e9f5b7/argparse_type_helper-0.2.3.tar.gz",
"platform": null,
"description": "# Argparse Type Helper\n\nA lightweight helper that lets you leverage type hints with `argparse`.\n\n## Installation\n\n```bash\npip install argparse-type-helper\n```\n\n## Features\n\n- **Class-based schema**\n Bundle all your arguments in a single `@targs`-decorated class.\n- **Identical API**\n Each field uses the same parameters as `argparse.add_argument` (`help`, `action`, `nargs`, etc.).\n- **Automatic registration**\n One call to `register_targs(parser, YourArgs)` wires up all arguments on your `ArgumentParser`.\n- **Typed extraction**\n After `parse_args()`, call `extract_targs()` to get a fully-typed instance of your class.\n- **Hybrid usage**\n Mix native `parser.add_argument(...)` calls with class-based definitions in the same parser.\n- **Docstring support**\n Use docstrings to automatically generate help text for your arguments.\n\n## Why not [typed-argparse](https://typed-argparse.github.io/typed-argparse/)?\n\ntyped-argparse is a great library, but it replaces the familiar `argparse.add_argument` API with its own argument-definition interface, which can be a hurdle when integrating into an existing codebase.\n\nargparse-type-helper, by contrast, is a simple helper that allows you to use type hints with argparse with minimal learning curve. It uses the same `argparse` API you\u2019re already familiar with, and you can even mix native `argparse` usage with class-based definitions in the same parser.\n\n## Usage\n\n<!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./tests/example.py) -->\n<!-- The below code snippet is automatically added from ./tests/example.py -->\n```py\nimport argparse\nimport sys\nfrom typing import Never\n\nfrom argparse_type_helper import (\n Flag,\n Name,\n extract_targs,\n post_init,\n register_targs,\n targ,\n targs,\n)\n\n\n# Define your typed arguments as a targ class\n@targs\nclass MyArgs:\n # This example will show the common usage of targ.\n\n positional: str = targ(Name, help=\"A positional argument (positional).\")\n custom_name_pos: str = targ(\n \"my_positional\", help=\"A custom named positional argument.\"\n )\n\n optional: str = targ(Flag, help=\"An optional argument (--optional).\")\n optional_dash: str = targ(\n Flag, help=\"underscore is replaced with dash (--optional-dash).\"\n )\n optional_short: str = targ(\n Flag(\"-s\"), help=\"You can also add a short name (-s, --optional-short).\"\n )\n custom_name_opt: str = targ(\n \"--my-optional\",\n help=\"A custom named optional argument.\",\n )\n custom_name_opt_short: str = targ(\n (\"-c\", \"--my-short-optional\"),\n help=\"A custom named optional argument with a short name. (note the tuple)\",\n )\n\n options: list[str] = targ(\n Flag,\n action=\"extend\",\n nargs=\"+\",\n default=[],\n help=\"All options (`help`, `action`, `nargs`, etc.) are the same as argparse.\",\n )\n choices: str = targ(\n Flag,\n choices=[\"option1\", \"option2\", \"option3\"],\n help=\"Another example argument with choices.\",\n )\n flag: bool = targ(\n Flag(\"-d\"), action=\"store_true\", help=\"Another example boolean flag.\"\n )\n\n default_type: int = targ(\n Flag,\n default=42,\n help=\"if type is not specified, it defaults to the type hint. (type=int in this case)\",\n )\n custom_type: float = targ(\n Flag,\n type=lambda x: round(float(x), 1),\n default=3.14,\n help=\"You can also specify a custom type\",\n )\n\n docstring_as_help: str = targ(Flag, default=\"default value\")\n \"\"\"\n If you don't specify a help, it will use the docstring as the help text.\n This is useful for documentation purposes.\n Your LSP will also pick this up.\n \"\"\"\n\n # You can also use the `post_init` decorator to execute some code after the arguments are extracted.\n # This is useful for validation or other post-processing.\n @post_init\n def validate(self) -> None:\n if self.positional == \"error\":\n raise ValueError(\"positional argument cannot be 'error'\")\n\n\n# You can register the targs with a custom parser\nclass MyParser(argparse.ArgumentParser):\n def error(self, message: str) -> Never:\n sys.stderr.write(\"error: %s\\n\" % message)\n self.print_help()\n sys.exit(2)\n\n\nif __name__ == \"__main__\":\n # Create a parser\n parser = MyParser(description=\"Process some data arguments.\")\n\n # Register the targs with the parser\n # verbose=True will print the registered arguments\n register_targs(parser, MyArgs, verbose=True)\n\n # Hybrid usage example\n parser.add_argument(\"--version\", action=\"version\", version=\"MyArgs 1.0.0\")\n\n # Parse the arguments\n args = parser.parse_args()\n\n # Extract the targs from the parsed arguments\n my_args = extract_targs(args, MyArgs)\n print(f\"Parsed arguments: {my_args}\")\n```\n<!-- MARKDOWN-AUTO-DOCS:END -->\n",
"bugtrack_url": null,
"license": null,
"summary": "an easy-to-integrate typed argument parser",
"version": "0.2.3",
"project_urls": {
"Bug Tracker": "https://github.com/lljbash/targs/issues",
"Homepage": "https://github.com/lljbash/targs"
},
"split_keywords": [
"argparse",
" typing",
" argument parser",
" type hints",
" typed arguments"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "af7317cc734605cd3eb2aae8d06e38b758beff98712a7e6767335dbfa0bb0c69",
"md5": "778ab20278c882f83e0a2310af96c473",
"sha256": "eec11f7c2d1f74e6171fae4fc9f7a6ec4389c50bed68b0ccb7f22a6069fd2f8e"
},
"downloads": -1,
"filename": "argparse_type_helper-0.2.3-py3-none-any.whl",
"has_sig": false,
"md5_digest": "778ab20278c882f83e0a2310af96c473",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 7860,
"upload_time": "2025-07-15T10:43:08",
"upload_time_iso_8601": "2025-07-15T10:43:08.468128Z",
"url": "https://files.pythonhosted.org/packages/af/73/17cc734605cd3eb2aae8d06e38b758beff98712a7e6767335dbfa0bb0c69/argparse_type_helper-0.2.3-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "68c6cdd65cb29306ff4e79966b0cf70a21bb727f88c70111b3ea020fb4e9f5b7",
"md5": "2a0a572ec67d29e22367feca61027622",
"sha256": "99ab186721a7715d1cef8c249e62a5c2d55d8ca140e09f9c88427bae31dbde5a"
},
"downloads": -1,
"filename": "argparse_type_helper-0.2.3.tar.gz",
"has_sig": false,
"md5_digest": "2a0a572ec67d29e22367feca61027622",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 11149,
"upload_time": "2025-07-15T10:43:09",
"upload_time_iso_8601": "2025-07-15T10:43:09.854999Z",
"url": "https://files.pythonhosted.org/packages/68/c6/cdd65cb29306ff4e79966b0cf70a21bb727f88c70111b3ea020fb4e9f5b7/argparse_type_helper-0.2.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-15 10:43:09",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lljbash",
"github_project": "targs",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "argparse-type-helper"
}