Many other programming languages have argument parsing libraries that operate by simply writing a struct, with some additional annotations. The parser then just returns an instance of that struct. The python standard lib has argparse which is quite flexible and powerful, but it returns a very dynamic Namespace object. Users either have to live with this dynamism and loss of error checking, or manually repeat many argument names and types.
Python does have some third party argument parsing libraries like click, but they diverge a lot more from argparse, and tend to also go a step further and directly run functions for you.
I’ve been messing around and with a relatively small amount of code, I’ve been able to write a handful of functions that allow you to write things like this
@dataclass
class MyArgs:
first_arg: int = positional()
second_arg: float | None = option()
ex1: ClassVar[Exclusive] = exclusive_group()
foo: int | None = option(exclusive_group=ex1, help="this is forwarded back to argparse")
bar: int | None = option(exclusive_group=ex1, metavar="so_is_this")
sub: SubCommand1 | SubCommand2 | None = subparsers(default=None)
print(parse_args(MyArgs))
usage: scratch.py [-h] [--second-arg SECOND_ARG] [--foo FOO | --bar so_is_this] first_arg {sub1,sub2} ...
positional arguments:
first_arg
{sub1,sub2}
options:
-h, --help show this help message and exit
--second-arg SECOND_ARG
--foo FOO this is forwarded back to argparse
--bar so_is_this
Almost everything is handled pretty transparently via forwarding back to argparse. It simply removes some of the boilerplate involved in repeated variable names and typing information. Since it’s not much code and nearly everything is simply forwarded back to argparse (it has almost no “behavior” of its own - just a few small but significant conveniences) - I thought maybe this would be suitable to add to the argparse module.
The closest thing I found was GitHub - mivade/argparse_dataclass: Declarative CLIs with argparse and dataclasses, but it has quite a bit more boilerplate, and also does not handle things like subparsers and mutual exclusion, I believe.
I think if something like this were added to the standard library, most people who use type checkers would simply use it instead of the current argparse API.