Skip to main content

Parse command line arguments by defining pydantic models

Project description

typed-args

A typed command-line argument parser for Python, inspired by Rust's clap. Define a pydantic model — its types drive the CLI, and parsing runs real runtime validation. Subcommands are discriminated unions you dispatch with match.

Requires Python 3.10+ and pydantic 2.

Installation

pip install typed-args

A first example

from typing import Annotated, List

import typed_args as ta
from pydantic import Field


class Args(ta.TypedArgs):
    model_config = ta.ParserConfig(description="Process some integers.")
    integers: Annotated[List[int], ta.Arg(metavar="N", nargs="+", help="an integer for the accumulator")]
    workers: Annotated[int, Field(gt=0, le=32), ta.Arg("-w", "--workers", help="worker count")] = 4


args = Args.parse_args()
print(args.integers, "max =", max(args.integers), "workers =", args.workers)
$ python prog.py 1 2 3 4 -w 8
[1, 2, 3, 4] max = 4 workers = 8

$ python prog.py 1 -w 99
workers
  Input should be less than or equal to 32 ...

The Field(gt=0, le=32) constraint is enforced at parse time — workers=99 raises a pydantic.ValidationError instead of silently producing a bad value.

How it works

  • Types drive structure. bool--flag (store_true), Literal[...]choices, listnargs, Optional/defaults → optional args, required scalars → positionals.
  • Arg(...) is the argparse passthrough. Attach it via Annotated[T, Arg(...)] for option strings, help, metavar, action, nargs, const, ... It overlays argparse params on top of the type-derived defaults.
  • Docstrings become help automatically. A bare string literal on the line after a field is used as its help text (via pydantic's use_attribute_docstrings, on by default). Precedence: Arg(help=...) > Field(description=...) > attribute docstring.
  • Validation is real. pydantic coerces and validates the parsed namespace, so Field(...), field_validator, and structured error messages all work.
  • Parser config is model_config. Use ParserConfig(prog=..., description=...), which subclasses pydantic's ConfigDict and mixes freely with pydantic config (frozen, str_strip_whitespace, ...). For full control, pass your own argparse.ArgumentParser via Args.parse_args(parser=...).

Subcommands

Subcommands are a pydantic discriminated union; dispatch with match:

from typing import Annotated, Literal, Union

import typed_args as ta
from pydantic import Field


class GlobalArgs(ta.TypedArgs):
    verbose: Annotated[bool, ta.Arg("-v", "--verbose")] = False


class AddArgs(ta.TypedArgs):
    cmd: Literal["add"] = "add"
    file: Annotated[str, ta.Arg(help="file to add")]
    force: Annotated[bool, ta.Arg("--force")] = False


class RemoveArgs(ta.TypedArgs):
    cmd: Literal["remove"] = "remove"
    file: Annotated[str, ta.Arg(help="file to remove")]
    recursive: Annotated[bool, ta.Arg("-r", "--recursive")] = False


class Root(ta.TypedArgs):
    common: GlobalArgs
    subcommand: Annotated[Union[AddArgs, RemoveArgs], Field(discriminator="cmd")]


root = Root.parse_args()
match root.subcommand:
    case AddArgs(file=f, force=True):
        print("force-add", f)
    case AddArgs(file=f):
        print("add", f)
    case RemoveArgs(file=f, recursive=True):
        print("recursive remove", f)
    case RemoveArgs(file=f):
        print("remove", f)

Global flags (the common field) work both before and after the subcommand.

API

  • TypedArgspydantic.BaseModel subclass adding parse_args(argv=None, *, parser=None) and parse_known_args(...) classmethods.
  • ParserConfigConfigDict subclass with argparse.ArgumentParser fields.
  • Arg(*option_strings, **kwargs) — argparse passthrough marker for a field.
  • parse(model, argv=None, *, parser=None) / parse_known_args(...) — free functions for users who don't subclass TypedArgs.
  • DefaultHelpFormatter — strips dotted dest prefixes from help output.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typed_args-0.7.0.tar.gz (7.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typed_args-0.7.0-py3-none-any.whl (10.5 kB view details)

Uploaded Python 3

File details

Details for the file typed_args-0.7.0.tar.gz.

File metadata

  • Download URL: typed_args-0.7.0.tar.gz
  • Upload date:
  • Size: 7.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for typed_args-0.7.0.tar.gz
Algorithm Hash digest
SHA256 34b5522a3e2ce94032bc428df2cbbb345b3c20e7be5ac005b45fe9086fa6c9cf
MD5 4a31dc833e465820938e61a35067e8e8
BLAKE2b-256 21890c2ab706051191026c25a82e6877f961da3fa82dad594efe4d7c28ee279a

See more details on using hashes here.

File details

Details for the file typed_args-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: typed_args-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 10.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for typed_args-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7196eca5cd30c8926349d5ac14822bc60b3e2526128369a7a11eaad92dd12f12
MD5 7709a7cc55634f9ad2fd9f475517bd86
BLAKE2b-256 7735555beb82cde594da5341d4ea649c62e026e6657f13133fe5ef93bf14daa4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page