argparse-wizard
argparse-wizard: Cleaner object-oriented argparse-driven command-line interfaces
Highlights
- Declare subcommands (including nested subcommands) as decorated async methods on a
CliBasesubclass instead of hand-wiringargparsesubparsers.CliBaseisn't generic, so subclasses are justclass MyCli(CliBase):— noCliBase["MyCli"]self-reference. Command methods spell out their own CLI type withtyping.Self(cmd: CliCommand[Self]), which stays correct even ifMyCliis further subclassed. - A command's
add_argument()calls live in the same method as the handler that reads them back offself.args— not in a separate parser-setup block you have to remember to keep in sync as the handler evolves. Add, rename, or remove an argument and its usage in one place; there's no second copy of the command's shape to drift out of sync with the first. - Command names and hierarchy are derived automatically from method names
(
cmd_test__list→test list), or can be given explicitly. - Built-in
--log-level,--tb,--input-file/--output-filehandling:-i/-oactually reopensys.stdin/sys.stdoutfor the duration of the command, so plainprint()/input()and any library that inspectssys.stdout(colorizers,rich, ...) transparently honor the redirection, the same way shell redirection would. The pre-redirection streams stay reachable viaself.orig_stdin/self.orig_stdout, andself.get_binary_stdin()/get_binary_stdout()give binary-safe access to whichever stream is currently in effect. CliError/CliExitfor clean, exit-code-driven error handling instead of rawsys.exit()calls.- Commands and pre-dispatch hooks are
async def. Run the CLI withcli.run()and it drives that internally viaasyncio.run(...)for you — noasyncioimport needed in your own code. Apps that already have (or want to control) their own event loop canawait cli.async_run()instead. - Fully typed (
py.typed), works undermypy --strict.
Installation
pip install argparse-wizard
Quick Start
import sys
from typing_extensions import Self
from argparse_wizard import CliBase, CliCommand, CliError, OptCmdFunc, cli_command
class GreetCli(CliBase):
@cli_command("Greet someone by name.")
async def cmd_hello(self, cmd: CliCommand[Self]) -> OptCmdFunc:
async def handler() -> None:
name: str = self.args.name
if not name:
raise CliError("--name must not be empty")
print(f"Hello, {name}!")
p = cmd.get_parser()
p.add_argument("--name", "-n", default="world")
return handler
@cli_command("Example CLI.")
async def main(self, cmd: CliCommand[Self]) -> OptCmdFunc:
return None # no bare handler: a subcommand is required
def main() -> int:
return GreetCli(sys.argv[1:]).run()
if __name__ == "__main__":
sys.exit(main())
$ python greet.py hello --name Ada
Hello, Ada!
See examples/greet.py for a fuller example with nested subcommands.
Supported Python Versions
Python 3.10 through 3.14.
License
MIT. See LICENSE.
For development and release workflow documentation, see CONTRIBUTING.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file argparse_wizard-1.0.0.tar.gz.
File metadata
- Download URL: argparse_wizard-1.0.0.tar.gz
- Upload date:
- Size: 16.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
941f04ed8723c209ee0ce6ff3ffc99635cc6a3e8523fa4ce83102b6650c23815
|
|
| MD5 |
e67f95c605291b801455e23674f8dcab
|
|
| BLAKE2b-256 |
f2647d5c6ab7c1cc80357be870dac4bd41f5ea08e2a83f5368f0d7d8183ca4cd
|
Provenance
The following attestation bundles were made for argparse_wizard-1.0.0.tar.gz:
Publisher:
publish.yml on mckelvie-org/argparse-wizard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
argparse_wizard-1.0.0.tar.gz -
Subject digest:
941f04ed8723c209ee0ce6ff3ffc99635cc6a3e8523fa4ce83102b6650c23815 - Sigstore transparency entry: 2216890833
- Sigstore integration time:
-
Permalink:
mckelvie-org/argparse-wizard@13ae2617108ba53a79801cadc19a18262564d5aa -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/mckelvie-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@13ae2617108ba53a79801cadc19a18262564d5aa -
Trigger Event:
push
-
Statement type:
File details
Details for the file argparse_wizard-1.0.0-py3-none-any.whl.
File metadata
- Download URL: argparse_wizard-1.0.0-py3-none-any.whl
- Upload date:
- Size: 16.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac4ac909cf6bae5b38cfd1f3e8ce7392d131c6794c787f1b5ff6fbb0c6c482ef
|
|
| MD5 |
e9cb2501a28ffb2a08fd058259935857
|
|
| BLAKE2b-256 |
e02bc4fa3693d8b6d89921346513ae46bd0f9719e7add15fad8e88a5363745ee
|
Provenance
The following attestation bundles were made for argparse_wizard-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on mckelvie-org/argparse-wizard
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
argparse_wizard-1.0.0-py3-none-any.whl -
Subject digest:
ac4ac909cf6bae5b38cfd1f3e8ce7392d131c6794c787f1b5ff6fbb0c6c482ef - Sigstore transparency entry: 2216890899
- Sigstore integration time:
-
Permalink:
mckelvie-org/argparse-wizard@13ae2617108ba53a79801cadc19a18262564d5aa -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/mckelvie-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@13ae2617108ba53a79801cadc19a18262564d5aa -
Trigger Event:
push
-
Statement type: