The Essentials¶
- starstar.divide(kw: dict, *funcs: Callable | Iterable[Callable], mode='strict', varkw: bool = True)[source]¶
Divide
**kwargsbetween multiple functions based on their signatures.- Parameters:
*funcs (callable) – The functions you want to divide arguments amongst.
mode (str) –
How to handle extra keyword arguments.
'separate': Add them as an extra dictionary at the end.'strict': If there are extra keyword arguments, raise aTypeError. This will only raise if no function with a variable keyword is found orvarkw == False.
varkw (bool | 'first') – Do we want to pass extra arguments as
**kwargsto any function that accepts them? By default (True), they will go to all functions with variable keyword arguments. If'first'they will only go to the first matching function. IfFalse, no function will get variable keyword args.
- Returns:
A dict for each function provided, plus one more for unused kwargs if
mode == 'separate'.- Raises:
TypeError – if
mode='strict'(default) and it receives arguments that don’t appear in any function’s signature. Does not apply if any function takes**kw.
Pass arguments to multiple functions!
def func_a(a=None, b=None, c=None): return a, b, c def func_b(d=None, e=None, f=None): return d, e, f def main(**kw): kw_a, kw_b = starstar.divide(kw, func_a, func_b) func_a(**kw_a) func_b(**kw_b) # and it even works for nested functions ! def func_c(**kw): kw_a, kw_b = starstar.divide(kw, func_a, func_b) func_a(**kw_a) func_b(**kw_b) def func_d(g=None, h=None, i=None): return g, h, i def main(**kw): kw_c, kw_d = starstar.divide(kw, (func_a, func_b), func_d) func_c(**kw_c) func_d(**kw_d)
Decide how you want to handle extra keyword args.
main(a=1, x=2) # extra argument "x" # divide raises TypeError def main(**kw): kw_a, kw_b, kw_extra = starstar.divide(kw, func_a, func_b, mode='separate') main(a=1, x=2) # extra argument "x" # gets put in ``kw_extra``
- starstar.traceto(*funcs: Callable, keep_varkw=None, filter_hidden=True, doc=False) Callable[source]¶
Tell a function where its
**kwargsare going!This is similar to
functools.wraps, except that it merges the signatures of multiple functions and only deals with arguments that can be passed as keyword arguments.- Parameters:
*funcs (callable) – The functions where the keyword arguments go.
keep_varkw (bool) – Whether we should keep
**kwin the signature. If not set, this will be True if any of the passed arguments take variable kwargs.filter_hidden (bool) – Whether we should filter out arguments starting with an underscore. Default True. This is often used for private arguments for example in the case of recursive functions that pass objects internally.
doc (bool) – Whether to merge the docstrings. Defaults to False.
By having
func_ctrace its**kwargssignature,maincan say that it’s passing its arguments tofunc_cand it will be able to see the parameters offunc_a&func_b.@starstar.traceto(func_a, func_b) def func_c(**kw): kw_a, kw_b = starstar.divide(kw, func_a, func_b) func_a(**kw_a) func_b(**kw_b) @starstar.traceto(func_c, func_d) def main(**kw): kw_c, kw_d = starstar.divide(kw, func_c, func_d) func_c(**kw_c) func_d(**kw_d)
- starstar.wraps(func: Callable, skip_args=(), skip_n=0) Callable[source]¶
functools.wraps, except that it merges the signature.Note
functools.wrapsdoesn’t do any function introspection. This means that if the wrapper function adds any arguments to the function signature, these arguments won’t be documented.If you’re not familiar with
functools.wraps, it is a decorator that renames a wrapper function and its signature to look like the function that it’s wrapping.# without wrapping def print_output(func): def inner(*a, print_output=True, **kw): output = func(*a, **kw) if print_output: print(output) return output return inner @print_output def something(a, b): return a+b assert something.__name__ == 'inner' # with wrapping def print_output(func): @starstar.wraps(func) def inner(*a, print_output=True, **kw): output = func(*a, **kw) if print_output: print(output) return output return inner @print_output def something(a, b): return a+b assert something.__name__ == 'something'
Argument Filtering¶
- starstar.filtered(func)[source]¶
A decorator that filters out any extra kwargs passed to a function. See
starstar.filterfor more information.@starstar.filtered def func_a(a, b, c): pass func_a(1, 2, c=3, x=1, y=2) # just gonna ignore x and y # using the decorator is equivalent to func_a(*a, **starstar.filter_kw(func_a, kw))
- starstar.filter_kw(func, kw, skip_n=0, pop=False, inverse=False, unmatched=False, include_varkw=True)[source]¶
Filter
**kwargsdown to only those that appear in the function signature.- Parameters:
func (callable) – The function to filter using.
kw – keyword arguments that you’d like to filter.
pop (bool) – Remove matched keys from kw.
inverse (bool) – Return keys not in function signature.
include_varkw (bool) – if a function takes **kw, should it swallow all arguments? default True.
- Returns:
the filtered
kwargs- Return type:
(dict)
def func_a(a, b, c): pass args = {'b': 2, 'c': 3, 'x': 1, 'y': 2} assert starstar.filter_kw(func_a, args) == {'b': 2, 'c': 3}