Funcgen¶
A small module for generating sets of function signatures and corresponding function objects.
Installation¶
funcgen requires Python >= 3.6 because it relies on modern type annotations.
pip install funcgen
Example¶
>>> import funcgen
>>>
>>> def wrapper(present):
... log(f'Wrapped {present.__name__}')
... return present
...
>>> def test_wrapper():
... for funcs in funcgen.all_valid_functions():
... assert all(wrapper(f) == f for f in funcs)
...
>>> test_wrapper()
API¶
Contents¶
This will generate every combination of the parameters and parameter attributes passed to it, if that combination results in a valid Python function signature. |
|
A convenience function that will generate an example of every category of valid function signature for Python. |
|
For every signature in |
|
A convenience function that feeds |
|
Takes in parameter names, defaults, and annotations and generates every sequence of parameters possible from every combination of those attributes. |
Documentation¶
-
funcgen.valid_signatures(args: Sequence[Tuple[Sequence[str], Sequence[Any], Sequence[Type]]] = [], kwargs: Sequence[Tuple[Sequence[str], Sequence[Any], Sequence[Type]]] = [], var_args: Tuple[Sequence[str], Sequence[Type]] = ([], []), var_kwargs: Tuple[Sequence[str], Sequence[Type]] = ([], []), return_annotations: Sequence[object] = [<class 'inspect._empty'>]) → Generator[inspect.Signature, None, None][source]¶ This will generate every combination of the parameters and parameter attributes passed to it, if that combination results in a valid Python function signature.
A
VarParamTupledescribes the range of attributes to give a variadic parameter. It is a tuple of two sequences: names and type annotations, respectively. The cross product of that tuple represents the range of attributes to give that parameter in the results.Use
Parameter.emptyto specify a missing type annotation or default value, andSignature.emptyto specify a missing return type annotation.>>> args = [(['arg1'], [Parameter.empty, 42], [int])] >>> kwargs = [] >>> var_args = (['args'], [float]) >>> var_kwargs = ([], []) >>> return_annotations = [Signature.empty, int] >>> [str(s) for s in valid_signatures(args, kwargs, var_args, var_kwargs, return_annotations)] ['()', '() -> int', '(*args:float)', '(*args:float) -> int', '(arg1:int)', '(arg1:int) -> int', '(arg1:int, *args:float)', '(arg1:int, *args:float) -> int', '(arg1:int=42)', '(arg1:int=42) -> int', '(arg1:int=42, *args:float)', '(arg1:int=42, *args:float) -> int']
- Parameters
args (Sequence[ParamTuple]) – A sequence of
ParamTuplesused to createParameter.POSITIONAL_OR_KEYWORDParameters(seevalid_parameters)kwargs (Sequence[ParamTuple]) – A sequence of
ParamTuplesused to createParameter.KEYWORD_ONLYParameters(seevalid_parameters)var_args (Sequence[VarParamTuple]) – A sequence of
VarParamTuplesused to createParameter.VAR_POSITIONALParameters(see above)var_kwargs (Sequence[VarParamTuple]) – A sequence of
VarParamTuplesused to createParameter.VAR_KEYWORDParameters(see above)return_annotations – A sequence of return annotations.
-
funcgen.all_valid_signatures() → Generator[inspect.Signature, None, None][source]¶ A convenience function that will generate an example of every category of valid function signature for Python. That is all combinations of
Zero, one, and two positional parameters with and without type annotations and default values.
Zero, one, and two keyword only parameters with and without type annotations and default values.
With and without *args, with and without a type annotation.
With and without **kwargs, with and without a type annotation.
With and without a return type annotation.
See the source for the call to
valid_signatures
-
funcgen.valid_functions(signatures: Iterable[inspect.Signature]) → Generator[Sequence[Callable], None, None][source]¶ For every signature in
signaturesthis function will yield a sequence of callable objects representing various forms that signature could take.Given an example signature like:
(arg1:int=42, *args:str, kwarg1=False, kwarg2:bool) -> bytes
The sequence yielded is equivalent to this:
# Regular function def f(arg1:int=42, *args:str, kwarg1=False, kwarg2:bool) -> bytes: pass # Bound Method class Foo: def f(arg1:int=42, *args:str, kwarg1=False, kwarg2:bool) -> bytes: pass # Static Class Method class FooStatic: @staticmethod def f(arg1:int=42, *args:str, kwarg1=False, kwarg2:bool) -> bytes: pass # Sequence yielded return f, Foo().f, FooStatic.f, FooStatic().f
- Parameters
signatures –
-
funcgen.all_valid_functions() → Generator[Sequence[Callable], None, None][source]¶ A convenience function that feeds
all_valid_signaturesintovalid_functionsto produce all callable forms of all valid signatures.
-
funcgen.valid_parameters(param_kind: inspect._ParameterKind, params: Sequence[Tuple[Sequence[str], Sequence[Any], Sequence[Type]]]) → Generator[List[inspect.Parameter], None, None][source]¶ Takes in parameter names, defaults, and annotations and generates every sequence of parameters possible from every combination of those attributes.
A
ParamTupleis a tuple of three sequences: names, default values, and annotations, respectively.paramsis a sequence ofParamTuplessuch that the cross product ofparams[i]represents the range of desired values for the ith parameter.Given every subset
params[:i]foriinrange(len(params)), this function will yield items from the cross product of the desired values for those parameters in the subset as a list ofParameters.If
param_kindisParameter.POSITIONAL_OR_KEYWORDorParameter.POSITIONAL_ONLY, then those lists where some parameter has a default value and previous parameter does not are not yielded because they would be invalid.Use
Parameter.emptyto specify the abscence of type annotation or default value.>>> [str(x) for x in valid_parameters(Parameter.POSITIONAL_OR_KEYWORD, ... [(['arg1'], ... [42, Parameter.empty], ... [int, Parameter.empty])])] ['[]', '[<Parameter "arg1:int=42">]', '[<Parameter "arg1=42">]', '[<Parameter "arg1:int">]', '[<Parameter "arg1">]']
>>> [str(x) for x in valid_parameters(Parameter.POSITIONAL_OR_KEYWORD, ... [(['arg1'], [42, Parameter.empty], [int]), ... (['arg2'], [107.7, Parameter.empty], [float])])] ['[]', '[<Parameter "arg1:int=42">]', '[<Parameter "arg1:int">]', '[<Parameter "arg1:int=42">, <Parameter "arg2:float=107.7">]', '[<Parameter "arg1:int">, <Parameter "arg2:float=107.7">]', '[<Parameter "arg1:int">, <Parameter "arg2:float">]']
>>> [str(x) for x in valid_parameters(Parameter.KEYWORD_ONLY, ... [(['arg1'], [42, Parameter.empty], [int]), ... (['arg2'], [107.7, Parameter.empty], [float])])] ['[]', '[<Parameter "arg1:int=42">]', '[<Parameter "arg1:int">]', '[<Parameter "arg1:int=42">, <Parameter "arg2:float=107.7">]', '[<Parameter "arg1:int">, <Parameter "arg2:float=107.7">]', '[<Parameter "arg1:int=42">, <Parameter "arg2:float">]', '[<Parameter "arg1:int">, <Parameter "arg2:float">]']
- Parameters
param_kind – must be
Parameter.POSITIONAL_ONLY,Parameter.KEYWORD_ONLY, orParameter.POSITIONAL_OR_KEYWORD.params (Sequence[ParamTuple]) –