clarify some things in typed_pos_args

This uses some variables to simplify some logic, and updates the
docstring to be more useful.
pull/8105/merge
Dylan Baker 4 years ago committed by Xavier Claessens
parent 2db7e24dbd
commit 8e73e5fe1c
  1. 57
      mesonbuild/interpreterbase.py

@ -253,28 +253,30 @@ def typed_pos_args(name: str, *types: T.Union[T.Type, T.Tuple[T.Type, ...]],
:optargs: The types of any optional arguments parameters taken. If None :optargs: The types of any optional arguments parameters taken. If None
then no optional paramters are taken. then no optional paramters are taken.
allows replacing this: Some examples of usage blow:
```python >>> @typed_pos_args('mod.func', str, (str, int))
def func(self, node, args, kwargs): ... def func(self, state: ModuleState, args: T.Tuple[str, T.Union[str, int]], kwargs: T.Dict[str, T.Any]) -> T.Any:
if len(args) != 2: ... pass
raise Exception('... takes exactly 2 arguments)
foo: str = args[0] >>> @typed_pos_args('method', str, varargs=str)
if not isinstance(foo, str): ... def method(self, node: BaseNode, args: T.Tuple[str, T.List[str]], kwargs: T.Dict[str, T.Any]) -> T.Any:
raise ... ... pass
bar: int = args[1]
if not isinstance(bar, int): >>> @typed_pos_args('method', varargs=str, min_varargs=1)
raise ... ... def method(self, node: BaseNode, args: T.Tuple[T.List[str]], kwargs: T.Dict[str, T.Any]) -> T.Any:
... pass
# actual useful stuff
``` >>> @typed_pos_args('method', str, optargs=[(str, int), str])
with: ... def method(self, node: BaseNode, args: T.Tuple[str, T.Optional[T.Union[str, int]], T.Optional[str]], kwargs: T.Dict[str, T.Any]) -> T.Any:
```python ... pass
@typed_pos_args('func_name', str, int)
def func(self, node, args: T.Tuple[str, int], kwargs): When should you chose `typed_pos_args('name', varargs=str,
foo, bar = args min_varargs=1)` vs `typed_pos_args('name', str, varargs=str)`?
# actual useful stuff The answer has to do with the semantics of the function, if all of the
``` inputs are the same type (such as with `files()`) then the former is
correct, all of the arguments are string names of files. If the first
argument is something else the it should be separated.
""" """
def inner(f: TV_func) -> TV_func: def inner(f: TV_func) -> TV_func:
@ -294,11 +296,12 @@ def typed_pos_args(name: str, *types: T.Union[T.Type, T.Tuple[T.Type, ...]],
a_types = types a_types = types
if varargs: if varargs:
num_types += min_varargs min_args = num_types + min_varargs
if max_varargs == 0 and num_args < num_types: max_args = num_types + max_varargs
raise InvalidArguments(f'{name} takes at least {num_types} arguments, but got {num_args}.') if max_varargs == 0 and num_args < min_args:
elif max_varargs != 0 and (num_args < num_types or num_args > num_types + max_varargs - min_varargs): raise InvalidArguments(f'{name} takes at least {min_args} arguments, but got {num_args}.')
raise InvalidArguments(f'{name} takes between {num_types} and {num_types + max_varargs - min_varargs} arguments, but got {len(args)}.') elif max_varargs != 0 and (num_args < min_args or num_args > max_args):
raise InvalidArguments(f'{name} takes between {min_args} and {max_args} arguments, but got {num_args}.')
elif optargs: elif optargs:
if num_args < num_types: if num_args < num_types:
raise InvalidArguments(f'{name} takes at least {num_types} arguments, but got {num_args}.') raise InvalidArguments(f'{name} takes at least {num_types} arguments, but got {num_args}.')

Loading…
Cancel
Save