From 9b5e4c809e7e37fbdf82d3f6ccb580d4c5896c17 Mon Sep 17 00:00:00 2001 From: Eric Ihli Date: Tue, 12 Dec 2023 20:19:11 -0800 Subject: [PATCH] Initial commit --- .gitignore | 2 ++ parsearger/__init__.py | 40 ++++++++++++++++++++++++++++++++++++++++ parsearger/__main__.py | 0 parsearger/test.py | 11 +++++++++++ parsearger/test1.py | 16 ++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 .gitignore create mode 100644 parsearger/__init__.py create mode 100644 parsearger/__main__.py create mode 100644 parsearger/test.py create mode 100644 parsearger/test1.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..36fa0f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.pyc +__pycache__ diff --git a/parsearger/__init__.py b/parsearger/__init__.py new file mode 100644 index 0000000..9d4b3ee --- /dev/null +++ b/parsearger/__init__.py @@ -0,0 +1,40 @@ +import argparse +from typing import TypeVar, Generic, cast + +Value = TypeVar("Value") + + +class Arg(Generic[Value]): + value: Value + + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + + def __set_name__(self, owner, name): + owner.arguments.append(name) + + def __get__(self, instance, owner) -> Value: + return self.value + + +class TypedNamespace(argparse.Namespace): + arguments = [] + @property + def descriptors(self): + return [(arg, self.__class__.__dict__[arg]) for arg in self.arguments] + + +Namespace = TypeVar("Namespace", bound=argparse.Namespace) + + +class ParseArger(argparse.ArgumentParser, Generic[Namespace]): + def __init__(self, *args, namespace: Namespace, **kwargs): + super().__init__(*args, **kwargs) + self.namespace = namespace + if namespace is not None: + for name, descriptor in namespace.descriptors: + self.add_argument(f"--{name.replace('_', '-')}", *descriptor.args, **descriptor.kwargs) + + def parse_args(self, args=None) -> Namespace: + return cast(Namespace, super().parse_args(args=args, namespace=self.namespace)) diff --git a/parsearger/__main__.py b/parsearger/__main__.py new file mode 100644 index 0000000..e69de29 diff --git a/parsearger/test.py b/parsearger/test.py new file mode 100644 index 0000000..269c45c --- /dev/null +++ b/parsearger/test.py @@ -0,0 +1,11 @@ +from parsearger import ParseArger, Arg, TypedNamespace + +class CliArgs(TypedNamespace): + num_things = Arg[int](help="Some help message", type=int) + name_thing = Arg[str](help="Name of some thing") + +namespace = CliArgs() +parser = ParseArger(namespace=namespace) +args = parser.parse_args() +args.num_things +args.name_thing diff --git a/parsearger/test1.py b/parsearger/test1.py new file mode 100644 index 0000000..29e2557 --- /dev/null +++ b/parsearger/test1.py @@ -0,0 +1,16 @@ +from collections import namedtuple +import argparse +parser = argparse.ArgumentParser() +parser.add_argument("--num-things", help="Number of things", type=int) +args.num_things + +parser = argparse.ArgumentParser() +parser.add_argument('--some-arg') +parser.add_argument('--another-arg') +MagicNamespace = namedtuple('MagicNamespace', [act.dest for act in parser._actions]) +mn = MagicNamespace() +mn.some_arg +mn.foo +parsed = parser.parse_args(['--some-arg', 'val1', '--another-arg', 'val2'], namespace=mn) +parsed.some_arg +parsed.foo