kwandl

Module Contents

Classes

ForwardNodeTransformer

Replace Call nodes with kwargs keywords in the AST of the decorated function.

Functions

get_kwargs_applicable_to_function(function, kwargs)

Returns a subset of kwargs of only arguments and keyword arguments of function.

_get_kwargs_applicable_to_function_and_check_expected_keywords(...)

Like get_kwargs_applicable_to_function, but also check expected keywords.

uncompile(c)

uncompile(codeobj) -> [source, filename, mode, flags, firstlineno].

recompile(source, filename, mode[, flags, firstlineno])

Recompile output of uncompile back to a code object. source may also be preparsed AST.

parse_snippet(source, filename, mode, flags, firstlineno)

Like ast.parse, but accepts indented code snippet with a line number offset.

_get_transitive_kwargs(me, downstream_dependency_functions)

Internal function to dynamically get the transitive kwargs of a function

forward(func)

forward_transitive(func)

Attributes

__version__

unparse

_forwarded_global

PyCF_MASK

kwandl.__version__ = 0.2.0[source]
kwandl.unparse[source]
kwandl._forwarded_global[source]
kwandl.get_kwargs_applicable_to_function(function, kwargs)[source]

Returns a subset of kwargs of only arguments and keyword arguments of function.

This can also include transitive keyword arguments: if a kwandl.forwarded function is called inside function, that inner function’s keyword arguments are also added here.

kwandl._get_kwargs_applicable_to_function_and_check_expected_keywords(function, function_call_name, kwargs, expected_keywords, local_function_names, typeerror_message)[source]

Like get_kwargs_applicable_to_function, but also check expected keywords.

This function is meant for use from @forward decorated functions that call non-global (i.e. local or non-local) objects. It adds the keywords from the local call (function) to expected_keywords, deletes function’s name from local_function_names and if local_function_names is empty (meaning all local functions have had their keywords added to expected_keywords) it finally does the unexpected keywords check. At this point it may raise an exception.

Input:
function_call_name: The name of function as it is used at the call site.

For instance, when calling thing.bla(kwarg=1) function_call_name must be “thing.bla”. This name will then be removed from local_function_names.

class kwandl.ForwardNodeTransformer(func, calling_decorator_name: str, transitive: bool = False)[source]

Bases: ast.NodeTransformer

Replace Call nodes with kwargs keywords in the AST of the decorated function.

This NodeTransformer is made to be used from function decorators. The **kwargs are wrapped in a function that filters out keywords that are not applicable to the function.

All applicable keywords of the called functions are also stored, so that they can be checked against in the modified function. This way, we can throw a TypeError when an unexpected keyword argument is given, except now it is unexpected by all the functions to which kwargs is forwarded.

The NodeTransformer parts are inspired by https://www.georgeho.org/manipulating-python-asts/

_add_funcs_kwparams_to_expected_kwargs(new_node)[source]
Returns: (called_name, non_global)
called_name: the function as it is called at the call site, e.g. “thing.bla”

when calling thing.bla(kwarg=1)

non_global: bool, True if the called function is a non-global (i.e. local or non-local)

visit_Call(node)[source]

Replace func(…,**kwargs) with func(…,**get_kwargs_applicable_to_function(func, kwargs)).

Also stores the names of the keyword arguments of all such `func`s in self.expected_kwargs.

visit_FunctionDef(node)[source]

Modify the function definition itself.

  • Rename and remove the decorator, otherwise we get infinite recursion.

  • Add a statement to the top checking if all kwargs are expected.

visit_stmt(node)[source]

In calls with kwandl-wrapped kwargs, we need to first reassign the to be called function to a new variable to avoid __get__`ting it twice. In case of exotic callables, like descriptors, which may return different functions with different sets of keyword arguments for different `__get__ calls, this will make sure it still works.

To put these reassignments in, we must visit the statements (ast.stmt) that contain the wrapped calls and return a reassignment statement followed by the original statement with the wrapped call.

visit_Expr(node)[source]
visit_Return(node)[source]
visit_Assign(node)[source]
visit_AnnAssign(node)[source]
visit_AugAssign(node)[source]
visit_Assert(node)[source]
visit_Raise(node)[source]
visit_If(node)[source]
visit_For(node)[source]
visit_While(node)[source]
kwandl.PyCF_MASK[source]
kwandl.uncompile(c)[source]

uncompile(codeobj) -> [source, filename, mode, flags, firstlineno].

kwandl.recompile(source, filename, mode, flags=0, firstlineno=1)[source]

Recompile output of uncompile back to a code object. source may also be preparsed AST.

kwandl.parse_snippet(source, filename, mode, flags, firstlineno)[source]

Like ast.parse, but accepts indented code snippet with a line number offset.

kwandl._get_transitive_kwargs(me, downstream_dependency_functions)[source]

Internal function to dynamically get the transitive kwargs of a function by walking through the list of downstream dependencies. This includes the kwargs of the function itself.

Pass in me manually at closure time as a poor-man’s self/class substitute.

kwandl.forward(func)[source]
kwandl.forward_transitive(func)[source]