front.util¶
Utils
-
front.util.
annotate_func_arguments
(func: Callable, *, ignore_existing_annot: bool = False, annot_for_argname: Union[Dict[str, Any], Iterable[Tuple[str, Any]]] = (), annot_for_dflt_type: Union[Dict[type, Any], Iterable[Tuple[type, Any]]] = (), dflt_annot: Any)[source]¶ Annotate
- Parameters
func – The function whose args we want to annotate
ignore_existing_annot – Set to True to ignore existing annots.
annot_for_argname – Annotation for specific argnames
annot_for_dflt_type – Annotation for specific types. Arg defaults will be compared (with
isinstance(dflt_val, types)
) to types and the annotation (value) of the the first matching type (key) will be injecteddflt_annot – Default annotation to use if no match found earlier. The default is inspect.Parameter.empty, which means “don’t annotate”. If you want all your params to be annotated no matter what, you might consider
typing.Any
, or in the case of command line interfaces,str
.
- Returns
A wrapped function with the desired signature changes, if any changes need to be made, or the same function untouched if not.
>>> from inspect import signature >>> from functools import partial >>> from typing import Any >>> >>> >>> def foo(a, b, c, aa: int=1, bb: int=1.0, cc: int=None, aaa=1, bbb=1.0, ccc=None): ... pass ...
If nothing changes, you just get back the same function:
>>> assert str(signature(annotate_func_arguments(foo))) == ( ... "(a, b, c, " ... "aa: int = 1, bb: int = 1.0, cc: int = None, " ... "aaa=1, bbb=1.0, ccc=None)" ... )
In the following:
b: str
through the argname rule, butbb
(as well asaa
andbb
)
didn’t change because
ignore_existing_annot=False
by default.aaa: float
(even though default is1
) andccc: 'NoneAnnot'
because of
the
annot_for_dflt_type
rules.>>> annotator = partial( ... annotate_func_arguments, ... annot_for_argname = {'b': str, 'bb': str}, ... # don't confuse following with dict(int=float), which means {'int': float} ... annot_for_dflt_type = {int: float, type(None): 'NoneAnnot'}, ... ) >>> >>> wrapped_func = annotator(foo) >>> assert str(signature(wrapped_func)) == ( ... "(a, b: str, c, " ... "aa: int = 1, bb: int = 1.0, cc: int = None, " ... "aaa: float = 1, bbb=1.0, ccc: 'NoneAnnot' = None)" ... )
See in the following what happens if we ask the default annotation to be
Any
andignore_existing_annot=True
:>>> another_annotator = partial( ... annotator, # use the previous one, but... ... dflt_annot=Any, # and specify a default annotation ... ignore_existing_annot=True # now ignore any existing annotations ... ) >>> >>> wrapped_func = another_annotator(foo) >>> assert str(signature(wrapped_func)) == ( ... "(a: Any, b: str, c: Any, " ... "aa: float = 1, bb: str = 1.0, cc: 'NoneAnnot' = None, " ... "aaa: float = 1, bbb: Any = 1.0, ccc: 'NoneAnnot' = None)" ... )
-
front.util.
incremental_str_maker
(str_format='{:03.f}')[source]¶ Make a function that will produce a (incrementally) new string at every call.
-
front.util.
obj_name
(func)[source]¶ The func.__name__ of a callable func, or makes and returns one if that fails. To make one, it calls unamed_func_name which produces incremental names to reduce the chances of clashing
-
front.util.
subdict
(d: Mapping, keys=None)[source]¶ Gets a sub-dict from a Mapping
d
, extracting only those keys that are both inkeys
andd
. Note that the dict will be ordered askeys
are, so can be used for reordering a Mapping.>>> subdict({'a': 1, 'b': 2, 'c': 3, 'd': 4}, keys=['b', 'a', 'd']) {'b': 2, 'a': 1, 'd': 4}