def f(*args, **kwargs):
""" Arbitrary interface function for illustration. """
f.parser.update(*args, **kwargs)
try:
print(f"a = {f.parser.get('a')}, b = {f.parser.get('b')}")
f.parser.close()
except Exception as err:
print(err)
pass13 Argument parsing
aka majordome_utilities.parsing
13.1 FuncArguments
- Arguments are both positional-mandatory
f.parser = FuncArguments()
f.parser.add("a", index=0)
f.parser.add("b", index=1)
f(3)
f(3, 4)Cannot retrieve mandatory positional argument at position 1
a = 3, b = 4
- Arguments are both keyword-only
f.parser = FuncArguments()
f.parser.add("a", default="foo")
f.parser.add("b", default="bar")
f(3)
f(3, 4)
f(3, b=4)
f(a=3, b=4)a = foo, b = bar
Too many positional arguments, got 1 but only 0 were used.
a = foo, b = bar
Too many positional arguments, got 2 but only 0 were used.
a = foo, b = 4
Too many positional arguments, got 1 but only 0 were used.
a = 3, b = 4
- One positional and another (maybe) positional
f.parser = FuncArguments()
f.parser.add("a", index=0)
f.parser.add("b", index=1, default=6)
f(3)
f(3, 4)
f(3, 4, b=4)a = 3, b = 6
a = 3, b = 4
Cannot have both positional and keyword version of b (1) simultaneously
- Badly configured
f.parser = FuncArguments()
try:
f.parser.add("a")
f.parser.add("b")
except Exception as err:
print(err)Argument must be either positional or keyword, cannot be neither: a
13.2 Creating class constructors
You should probably not do this, but it is quite fun!
def _init_some_class(cls):
""" Decorator to enhance SomeClass with argument parsing. """
orig_init = cls.__init__
# Maybe stash for later use?
# cls.__orig_init__ = orig_init
parser = FuncArguments(greedy_args=False, pop_kw=True)
parser.add("a", 0)
parser.add("x", default=None)
@wraps(orig_init)
def new_init(self, *args, **kwargs):
parser.update(*args, **kwargs)
a = parser.get("a")
x = parser.get("x")
orig_init(self, *parser.args, **parser.kwargs)
parser.close()
# -- logic goes here
print(f"some a = {a}")
print(f"some x = {x}")
return None
cls.__init__ = update_wrapper(new_init, orig_init)
return clsclass BaseClass:
def __init__(self, *args, **kwargs) -> None:
print(f"args = {args}")
print(f"kwargs = {kwargs}")@_init_some_class
class SomeClass(BaseClass):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)some = SomeClass(1, 2, 3, x=1, y=2)args = (1, 2, 3)
kwargs = {'y': 2}
some a = 1
some x = 1