argparcel
A minimalist library to parse command-line arguments into a dataclass.
Example usage
# examples/example_0.py
import dataclasses
import argparcel
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
class Args:
a: int
b: float
# A `bool` argument will create a linked pair of flags `--c` and `--no-c`.
c: bool
# A command line argument will be optional if and only if a default value is
# provided in the corresponding dataclass field.
d: str | None = None
if __name__ == "__main__":
print(argparcel.parse(Args))
$ uv run examples/example_0.py --help
usage: example_0.py [-h] --a A --b B --c | --no-c [--d D]
options:
-h, --help show this help message and exit
--a A
--b B
--c, --no-c
--d D
$ uv run examples/example_0.py --a 2 --b 3.2 --c
Args(a=2, b=3.2, c=True, d=None)
$ uv run examples/example_0.py --a 2 --b 3.2 --no-c
Args(a=2, b=3.2, c=False, d=None)
$ uv run examples/example_0.py --a 2 --b 3.2 --no-c --d moo
Args(a=2, b=3.2, c=False, d='moo')
We also support:
LiteralandEnums forcing specific choices- conversion to types whose
__init__accepts a string, e.g.pathlib.Path - annotated lists, e.g.
list[int]orlist[pathlib.Path] - annotated homogeneous tuples, e.g.
tuple[int, int]ortuple[str, ...] - 'help' can be provided too
# examples/example_1.py
import dataclasses
import enum
import pathlib
from typing import Literal
import argparcel
class Bird(enum.Enum):
puffin = enum.auto()
lark = enum.auto()
@dataclasses.dataclass(kw_only=True, frozen=True, slots=True)
class Args:
# Using a `Literal` will force a choice between 1, 2, or 3.
a: Literal[1, 2, 3]
# An enum will force a choice between the names of the enum elements.
b: Bird = Bird.puffin
# A `Path` can be automatically converted from a string. Here we also specify a
# 'help' message by using a 'docstring' for the field.
c: pathlib.Path | None = None
"""An important path."""
# A list will introduce a flag that consumes zero or more elements.
d: list[float] | None = None
# A tuple can require exactly a certain number of elements to be specified.
e: tuple[int, int] | None = None
# A tuple can also have an unknown number of elements.
f: tuple[str, ...] | None = None
# A tuple can also be required to have one or more elements.
g: tuple[float, *tuple[float, ...]] | None = None
if __name__ == "__main__":
print(argparcel.parse(Args))
$ uv run examples/example_1.py --help
usage: example_1.py [-h] --a {1,2,3} [--b {puffin,lark}] [--c C] [--d [D ...]] [--e E E]
options:
-h, --help show this help message and exit
--a {1,2,3}
--b {puffin,lark}
--c C An important path.
--d [D ...]
--e E E
$ uv run examples/example_1.py --a 2
Args(a=2, b=<Bird.puffin: 1>, c=None, d=None, e=None)
$ uv run examples/example_1.py --a 2 --b lark --c /somewhere/to/go
Args(a=2, b=<Bird.lark: 2>, c=PosixPath('/somewhere/to/go'), d=None, e=None)
$ uv run examples/example_1.py --a 2 --b lark --d 1.0 2.0 3.0
Args(a=2, b=<Bird.lark: 2>, c=None, d=[1.0, 2.0, 3.0])
$ uv run examples/example_1.py --a 2 --e 4 5
Args(a=2, b=<Bird.puffin: 1>, c=None, d=None, e=(4, 5))
Pitfall: forward-references
All types used in annotations must be available at runtime.
Specifically, when you call argparcel.parse(Args), internally it relies upon
typings.get_type_hints(Args) working. It will not work if any of the type annotations
for fields in Args can't be resolved at runtime.
A plausible scenario for this to fail is when using forward references.
Forward references are used when:
- annotating with a string, or
- you have
from future import __annotations__in the module, or - you're using Python 3.14 or later.
In any of these cases, a linter rule like ruff's TC003 may encourage you to move an import into a TYPE_CHECKING-guarded block, like so:
from __future__ import annotations
import dataclasses
from typing import TYPE_CHECKING
import argparcel
if TYPE_CHECKING:
from pathlib import Path
@dataclasses.dataclass
class Args:
x: Path
argparcel.parse(Args) # Raises NameError
But if you run this, you'll get:
<...snip stack trace...>
NameError: name 'Path' is not defined
Solutions
If you run into this issue, take your pick from the following solutions:
- Suppress your linter to permit the runtime import.
- Alternatively, use the
argparcel.uses_typesdecorator when defining the dataclass:
@argparcel.uses_types(Path)
@dataclasses.dataclass
class Args:
x: Path
This decorator is only a convenience to allow the user to indicate to their linter that the type is required. There's no requirement to specify all types that the dataclass uses.
- Use your own contrivance to ensure that the types are referenced at runtime.
Metadata
Release files for argparcel 0.0.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| argparcel-0.0.9.tar.gz | 8.8 kB | Without provenance | Details for argparcel-0.0.9.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| argparcel-0.0.9-py3-none-any.whl | Python 3 | none | any | Details for argparcel-0.0.9-py3-none-any.whl |
Total release size: 18.0 kB
Release files / argparcel-0.0.9.tar.gz
| Download URL | argparcel-0.0.9.tar.gz |
|---|---|
| Size | 8.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c60d3b008b25bf0cdaaf405045e53e3c36a1301503914f50ab50464b7a9273d2
|
|
BLAKE2b-256 checksum How to use checksums |
e11cb4dcfedd94f036dd792c6fa783b2bb73071d8670f2161c4639543b17ee83
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / argparcel-0.0.9-py3-none-any.whl
| Download URL | argparcel-0.0.9-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
271ebe634c997b4dc97692c47e2ac33f8ef98277219414fcb59051f8fca0bd9c
|
|
BLAKE2b-256 checksum How to use checksums |
52faf0a08152d3ca947ada22298585a60b655142a83d414de329ed82b3c4a775
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.32 {"installer":{"name":"uv","version":"0.11.32","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for argparcel 0.0.9
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.