Changelog
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
0.2.0 - 2026-07-16
Added
- Subcommand aliases: set
_parseraliases_on anArgssubclass to register short/alternate names for it in a_subcommands_tree (e.g._parseraliases_ = ["c"]soapp cruns the same command asapp create). Aliases dispatch to the same__call__. Absence of the attr is the unchanged default (no aliases). __version__fallback for--version: when_version_is unset, a class-level__version__string is now used to populate the--versionflag, so an app already carrying the conventional__version__gets--versionfor free._version_still wins when both are set (and remains the only form that accepts theduho.AUTOsentinel).
Changed
- BREAKING: the command-dispatch hook is renamed from
__run__to__call__. AnArgsinstance is now directly callable —instance()runs the command — andduho.main()dispatches toinstance.__call__(). Renamedef __run__(self)todef __call__(self)on your command classes.
0.1.1 - 2026-07-14
Added
- Documentation site at https://jose-pr.github.io/duho/ — guides for declaring arguments, types and conversion, running your app, configuration layers, logging, and shell completion, plus a generated API reference.
Changed
- Corrected the performance figures in the release notes to numbers measured on a fixed CI runner. Parser construction is 40–70× faster than the uncached path (10.5–11.0 ms → 0.15–0.27 ms, median, on Python 3.9 and 3.13); the previously published multiplier came from a noisy development machine.
Fixed
- README links to
LICENSEare absolute, so they resolve on the PyPI project page rather than 404ing.
0.1.0 - 2026-07-14
Initial release.
Added
- Declarative
Argsclasses — define a CLI by annotating class fields. The field's docstring becomes its help text and a following tuple literal declares its flags (("--name", "-n")); with no tuple, the flag is derived from the field name (dry_run→--dry-run). - Type-driven conversion from annotations:
str/int/float/bool,typing.Literal(→choices),enum.Enum(members matched by name),list[T](repeated or space-separated),Optional[T], andUnion[A, B](including PEP 604A | Bon 3.10+). Enums inside aUnion/Optionalare matched by member name, consistently with bare enum fields. - Positional arguments — a flag tuple with no leading dash (
("source",)); a positional with a default becomes optional (nargs="?"). - Full argparse passthrough via
Arg[T, NS(...)]—action,nargs,const,metavar,dest,choices, and any otheradd_argumentkeyword, plusNS(conflicts="group")for mutually exclusive groups. - Argument helpers:
Count(),Append(),Const(),Choice(),Extend(), and theUpdateActionaction. - Entry points:
duho.parser(cls)builds a parser;duho.parse(spec, argv)builds and parses in one call — passing an instance layers CLI overrides on top of its field values (CLI > instance > class default) and returns a new instance without mutating the original. - Command dispatch:
duho.main(cls, argv=None)builds, parses, sets up logging, and calls the selected instance's__run__()._subcommands_builds nested subparser trees automatically and dispatches to the deepest selected class. - Layered defaults: per-field environment variables via
NS(env="VAR")and TOML config files via_config_/config=, with the precedence ladder CLI > env > config > class default. Any layer supplying a value also un-requires that field.duho.value_sources(parsed)reports which layer won for each field. --version: set_version_to a string, or toduho.AUTOto resolve it from installed package metadata (_distribution_overrides the distribution name). When the distribution isn't installed, no--versionflag is added rather than printing a bogus version.- Shell completion: opt in with
_completion_ = Trueto add--print-completion {bash,zsh,fish}, or callduho.print_completion(). Scripts are generated statically — no runtime dependency and no re-invoking your program on every keypress. LoggingArgspreset —-v/-qcounted verbosity (offsetting, clamped at each end of the scale),--loglevelfor global or per-module levels, colored stderr output (optionalcolorama), and aTRACElevel.- Type hints ship with the package (
py.typed).
Notes
- Zero required runtime dependencies. Optional extras:
colorama(colored logging) andconfig(TOML on Python 3.9/3.10, wheretomllibisn't stdlib). - Supports Python 3.9 through 3.13.