Requirements
Requires Python 3.10+, and is compatible with the Pydantic library. Use Rich for better console output.
Installation
Installation with pip is simple:
$ pip install argparse-dantic
Example
from argparse_dantic import ArgumentParser, BaseModel, ArgumentField
class Arguments(BaseModel):
"""Simple Command-Line Arguments."""
# Required Args
string: str = ArgumentField("-s", description="a required string")
integer: int = ArgumentField("-i", description="a required integer")
flag: bool = ArgumentField("-f", description="a required flag")
# Optional Args
second_flag: bool = ArgumentField("-sec", default=False, description="an optional flag")
third_flag: bool = ArgumentField("-thi", default=True, description="an optional flag")
def main() -> None:
"""Simple Main Function."""
# Create Parser and Parse Args
parser = ArgumentParser(
model_class=Arguments,
prog="Example Program",
description="Example Description",
version="0.0.1",
epilog="Example Epilog",
)
args = ["-h"]
arguments = parser.parse_typed_args(args)
# Print Args
print(arguments)
if __name__ == "__main__":
main()
$ python3 example.py --help
Example Description
Usage: Example Program [-h] [-v] [--s STRING] [--i INTEGER] [--f] [--sec] [--no-thi]
Optional Arguments:
-s, --string STRING a required string (default: None)
-i, --integer INTEGER
a required integer (default: None)
-f, --flag a required flag (default: None)
-sec, --second-flag an optional flag (default: False)
-no-thi, --no-third-flag
an optional flag (default: True)
Help:
-h, --help show this help message and exit
-v, --version show program's version number and exit
Example Epilog
$ python3 example.py --string hello -i 42 -f
string='hello' integer=42 flag=True second_flag=False third_flag=True
Advanced Example
from typing import Annotated, Any, TypedDict, Literal
from argparse_dantic import (
BaseModel, ArgumentParser, CommandNameBind,
ArgumentField, CommandField, ModelField,
create_group
)
type LogLevels = Literal["debug", "info", "warning", "error", "critical"]
class GlobalData(TypedDict):
verbose: bool
quiet: bool
logging: "LoggingModel"
MGroup = create_group("Mutually Exclusive Group", "Mutually Exclusive Group Description").\
create_mutually_exclusive_group(required=False)
class MutuallyGroup(BaseModel, group=MGroup):
verbose: Annotated[bool, ArgumentField(default=False, description="Verbose Mode")]
quiet: Annotated[bool, ArgumentField(default=False, description="Quiet Mode")]
class LoggingModel(BaseModel):
level: Annotated[LogLevels, ArgumentField("l", default="info", description="Logging Level", env="ARGPARSE_DANTIC_TEST_LOG_LEVEL")]
file: Annotated[str, ArgumentField("f", default="app.log", description="Log File", env="ARGPARSE_DANTIC_TEST_LOG_FILE")]
class GlobalModel(MutuallyGroup):
global_data: GlobalData
logging: Annotated[LoggingModel, ModelField(connect_char=".")]
class BaseCommandModel(GlobalModel):
command_name: CommandNameBind
class BuildCommand(GlobalModel):
name: Annotated[str, ArgumentField(description="Project Name")]
version: Annotated[str, ArgumentField(description="Project Version")]
class ListToolsCommand(GlobalModel):
...
class ListInstallCommand(GlobalModel):
...
class ListCommand(BaseCommandModel):
tools: Annotated[ListToolsCommand, CommandField(description="List Tools Command")]
install: Annotated[ListInstallCommand, CommandField(description="List Install Command")]
class MainModel(BaseCommandModel):
build: Annotated[BuildCommand, CommandField(aliases=["bd"], description="Build Command")]
list: Annotated[ListCommand, CommandField(aliases=["ls"], description="Check Command")]
class Commands:
def __init__(self):
self.commands = {}
def register(self, name = None, parent = None):
def decorator(func):
nonlocal name
if name is None:
name = func.__name__
if parent is not None:
name = f"{parent}.{name}"
self.commands[name] = func
return func
return decorator
def __call__(self, name, parent = None) -> Any:
if parent:
name = f"{parent}.{name}"
return self.commands[name]
commands = Commands()
@commands.register()
def build(arguments: BuildCommand):
print(f"Building {arguments.name} version {arguments.version}")
@commands.register(name="list")
def list_(arguments: ListCommand):
commands(arguments.command_name, "list")(getattr(arguments, arguments.command_name))
@commands.register(parent="list")
def tools(arguments: ListToolsCommand):
print("List of tools")
@commands.register(parent="list")
def install(arguments: ListInstallCommand):
print("List of installed binaries")
if __name__ == "__main__":
parser = ArgumentParser(
model_class=MainModel,
prog="Advanced Example",
description="Advanced Example Description",
version="1.0.0"
)
args = ["build", "--name", "MyProject", "--logging.level", "error", "--quiet"]
arguments = parser.parse_typed_args(args)
parser.console.print("Global Data:")
parser.console.print("\tverbose:", arguments.global_data["verbose"])
parser.console.print("\tquiet:", arguments.global_data["quiet"])
parser.console.print("Logging Config:")
parser.console.print("\tlevel:", arguments.global_data["logging"].level)
parser.console.print("\tfile:", arguments.global_data["logging"].file)
try:
commands(arguments.command_name)(getattr(arguments, arguments.command_name))
except KeyError:
if arguments.command_name is None:
parser.console.print("No command specified")
else:
parser.console.print(f"Command {arguments.command_name} not found")
License
This project is licensed under the terms of the MIT license.
Thanks
Thanks to Pydantic and Rich for making this project possible.
Metadata
Release files for argparse-dantic 0.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| argparse_dantic-0.2.4.tar.gz | 71.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| argparse_dantic-0.2.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 152.5 kB
Release files / argparse_dantic-0.2.4.tar.gz
| Download URL | argparse_dantic-0.2.4.tar.gz |
|---|---|
| Size | 71.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
691d802ab8ea9f873f9ea6e6a34d604e22cfebb7cd68310377d147b1698bbda8
|
|
BLAKE2b-256 checksum How to use checksums |
5b7a38b2d84a422e807dcc9e320b74c8621a4be30ce59194f1973502a25fe548
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / argparse_dantic-0.2.4-py3-none-any.whl
| Download URL | argparse_dantic-0.2.4-py3-none-any.whl |
|---|---|
| Size | 80.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f11ed39895b04e8fa3fa5e0ffc1b28f19711890e240f402e0c7dfc1b4142f3c5
|
|
BLAKE2b-256 checksum How to use checksums |
3f5293f221aef03d5d56ebf90a2b5051ff5291b0f7e9b6249b740c02d92cc438
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|