funcutils
- functools
fixes¶
Python’s built-in functools
module builds several useful
utilities on top of Python’s first-class function
support. funcutils
generally stays in the same vein, adding to and
correcting Python’s standard metaprogramming facilities.
Decoration¶
Decorators are among Python’s most elegant and succinct language features, and boltons adds one special function to make them even more powerful.
-
boltons.funcutils.
wraps
(func, injected=None, expected=None, **kw)[source]¶ Decorator factory to apply update_wrapper() to a wrapper function.
Modeled after built-in
functools.wraps()
. Returns a decorator that invokes update_wrapper() with the decorated function as the wrapper argument and the arguments to wraps() as the remaining arguments. Default arguments are as for update_wrapper(). This is a convenience function to simplify applying partial() to update_wrapper().Same example as in update_wrapper’s doc but with wraps:
>>> from boltons.funcutils import wraps >>> >>> def print_return(func): ... @wraps(func) ... def wrapper(*args, **kwargs): ... ret = func(*args, **kwargs) ... print(ret) ... return ret ... return wrapper ... >>> @print_return ... def example(): ... '''docstring''' ... return 'example return value' >>> >>> val = example() example return value >>> example.__name__ 'example' >>> example.__doc__ 'docstring'
Function construction¶
Functions are so key to programming in Python that there will even arise times where Python functions must be constructed in Python. Thankfully, Python is a dynamic enough to make this possible. Boltons makes it easy.
-
class
boltons.funcutils.
FunctionBuilder
(name, **kw)[source]¶ The FunctionBuilder type provides an interface for programmatically creating new functions, either based on existing functions or from scratch.
Values are passed in at construction or set as attributes on the instance. For creating a new function based of an existing one, see the
from_func()
classmethod. At any point,get_func()
can be called to get a newly compiled function, based on the values configured.>>> fb = FunctionBuilder('return_five', doc='returns the integer 5', ... body='return 5') >>> f = fb.get_func() >>> f() 5 >>> fb.varkw = 'kw' >>> f_kw = fb.get_func() >>> f_kw(ignored_arg='ignored_val') 5
Note that function signatures themselves changed quite a bit in Python 3, so several arguments are only applicable to FunctionBuilder in Python 3. Except for name, all arguments to the constructor are keyword arguments.
Parameters: - name (str) – Name of the function.
- doc (str) – Docstring for the function, defaults to empty.
- module (str) – Name of the module from which this function was imported. Defaults to None.
- body (str) – String version of the code representing the body
of the function. Defaults to
'pass'
, which will result in a function which does nothing and returnsNone
. - args (list) – List of argument names, defaults to empty list, denoting no arguments.
- varargs (str) – Name of the catch-all variable for positional
arguments. E.g., “args” if the resultant function is to have
*args
in the signature. Defaults to None. - varkw (str) – Name of the catch-all variable for keyword
arguments. E.g., “kwargs” if the resultant function is to have
**kwargs
in the signature. Defaults to None. - defaults (tuple) – A tuple containing default argument values for those arguments that have defaults.
- kwonlyargs (list) – Argument names which are only valid as keyword arguments. Python 3 only.
- kwonlydefaults (dict) – A mapping, same as normal defaults, but only for the kwonlyargs. Python 3 only.
- annotations (dict) – Mapping of type hints and so forth. Python 3 only.
- filename (str) – The filename that will appear in tracebacks. Defaults to “boltons.funcutils.FunctionBuilder”.
- indent (int) – Number of spaces with which to indent the function body. Values less than 1 will result in an error.
- dict (dict) – Any other attributes which should be added to the functions compiled with this FunctionBuilder.
All of these arguments are also made available as attributes which can be mutated as necessary.
-
add_arg
(arg_name, default=NO_DEFAULT, kwonly=False)[source]¶ Add an argument with optional default (defaults to
funcutils.NO_DEFAULT
). Pass kwonly=True to add a keyword-only argument
-
classmethod
from_func
(func)[source]¶ Create a new FunctionBuilder instance based on an existing function. The original function will not be stored or modified.
-
get_defaults_dict
()[source]¶ Get a dictionary of function arguments with defaults and the respective values.
-
get_func
(execdict=None, add_source=True, with_dict=True)[source]¶ Compile and return a new function based on the current values of the FunctionBuilder.
Parameters: - execdict (dict) – The dictionary representing the scope in which the compilation should take place. Defaults to an empty dict.
- add_source (bool) – Whether to add the source used to a
special
__source__
attribute on the resulting function. Defaults to True. - with_dict (bool) – Add any custom attributes, if applicable. Defaults to True.
To see an example of usage, see the implementation of
wraps()
.
-
get_sig_str
(with_annotations=True)[source]¶ Return function signature as a string.
with_annotations is ignored on Python 2. On Python 3 signature will omit annotations if it is set to False.
-
remove_arg
(arg_name)[source]¶ Remove an argument from this FunctionBuilder’s argument list. The resulting function will have one less argument per call to this function.
Parameters: arg_name (str) – The name of the argument to remove. Raises a
ValueError
if the argument is not present.
Improved partial
¶
-
boltons.funcutils.
partial
¶
-
class
boltons.funcutils.
InstancePartial
[source]¶ functools.partial
is a huge convenience for anyone working with Python’s great first-class functions. It allows developers to curry arguments and incrementally create simpler callables for a variety of use cases.Unfortunately there’s one big gap in its usefulness: methods. Partials just don’t get bound as methods and automatically handed a reference to
self
. TheInstancePartial
type remedies this by inheriting fromfunctools.partial
and implementing the necessary descriptor protocol. There are no other differences in implementation or usage.CachedInstancePartial
, below, has the same ability, but is slightly more efficient.
-
class
boltons.funcutils.
CachedInstancePartial
[source]¶ The
CachedInstancePartial
is virtually the same asInstancePartial
, adding support for method-usage tofunctools.partial
, except that upon first access, it caches the bound method on the associated object, speeding it up for future accesses, and bringing the method call overhead to about the same as non-partial
methods.See the
InstancePartial
docstring for more details.
Miscellaneous metaprogramming¶
-
boltons.funcutils.
copy_function
(orig, copy_dict=True)[source]¶ Returns a shallow copy of the function, including code object, globals, closure, etc.
>>> func = lambda: func >>> func() is func True >>> func_copy = copy_function(func) >>> func_copy() is func True >>> func_copy is not func True
Parameters: - orig (function) – The function to be copied. Must be a function, not just any method or callable.
- copy_dict (bool) – Also copy any attributes set on the function
instance. Defaults to
True
.
-
boltons.funcutils.
dir_dict
(obj, raise_exc=False)[source]¶ Return a dictionary of attribute names to values for a given object. Unlike
obj.__dict__
, this function returns all attributes on the object, including ones on parent classes.
-
boltons.funcutils.
mro_items
(type_obj)[source]¶ Takes a type and returns an iterator over all class variables throughout the type hierarchy (respecting the MRO).
>>> sorted(set([k for k, v in mro_items(int) if not k.startswith('__') and 'bytes' not in k and not callable(v)])) ['denominator', 'imag', 'numerator', 'real']
-
boltons.funcutils.
format_invocation
(name='', args=(), kwargs=None, **kw)[source]¶ Given a name, positional arguments, and keyword arguments, format a basic Python-style function call.
>>> print(format_invocation('func', args=(1, 2), kwargs={'c': 3})) func(1, 2, c=3) >>> print(format_invocation('a_func', args=(1,))) a_func(1) >>> print(format_invocation('kw_func', kwargs=[('a', 1), ('b', 2)])) kw_func(a=1, b=2)
-
boltons.funcutils.
format_exp_repr
(obj, pos_names, req_names=None, opt_names=None, opt_key=None)[source]¶ Render an expression-style repr of an object, based on attribute names, which are assumed to line up with arguments to an initializer.
>>> class Flag(object): ... def __init__(self, length, width, depth=None): ... self.length = length ... self.width = width ... self.depth = depth ...
That’s our Flag object, here are some example reprs for it:
>>> flag = Flag(5, 10) >>> print(format_exp_repr(flag, ['length', 'width'], [], ['depth'])) Flag(5, 10) >>> flag2 = Flag(5, 15, 2) >>> print(format_exp_repr(flag2, ['length'], ['width', 'depth'])) Flag(5, width=15, depth=2)
By picking the pos_names, req_names, opt_names, and opt_key, you can fine-tune how you want the repr to look.
Parameters: - obj (object) – The object whose type name will be used and attributes will be checked
- pos_names (list) – Required list of attribute names which will be rendered as positional arguments in the output repr.
- req_names (list) – List of attribute names which will always appear in the keyword arguments in the output repr. Defaults to None.
- opt_names (list) – List of attribute names which may appear in the keyword arguments in the output repr, provided they pass the opt_key check. Defaults to None.
- opt_key (callable) – A function or callable which checks whether
an opt_name should be in the repr. Defaults to a
None
-check.
-
boltons.funcutils.
format_nonexp_repr
(obj, req_names=None, opt_names=None, opt_key=None)[source]¶ Format a non-expression-style repr
Some object reprs look like object instantiation, e.g., App(r=[], mw=[]).
This makes sense for smaller, lower-level objects whose state roundtrips. But a lot of objects contain values that don’t roundtrip, like types and functions.
For those objects, there is the non-expression style repr, which mimic’s Python’s default style to make a repr like so:
>>> class Flag(object): ... def __init__(self, length, width, depth=None): ... self.length = length ... self.width = width ... self.depth = depth ... >>> flag = Flag(5, 10) >>> print(format_nonexp_repr(flag, ['length', 'width'], ['depth'])) <Flag length=5 width=10>
If no attributes are specified or set, utilizes the id, not unlike Python’s built-in behavior.
>>> print(format_nonexp_repr(flag)) <Flag id=...>