Reference: aspectlib
¶
Overview¶
Safe toolkit for writing decorators (hereby called aspects)
aspectlib.Aspect |
Container for the advice yielding generator. |
aspectlib.Proceed |
Instruction for calling the decorated function. |
aspectlib.Return |
Instruction for returning a optional value. |
Power tools for patching functions (hereby glorified as weaving)
aspectlib.ALL_METHODS |
Compiled regular expression objects |
aspectlib.NORMAL_METHODS |
Compiled regular expression objects |
aspectlib.weave |
Send a message to a recipient |
aspectlib.Rollback |
When called, rollbacks all the patches and changes the weave() has done. |
Reference¶
-
class
aspectlib.
Proceed
(*args, **kwargs)[source]¶ Instruction for calling the decorated function. Can be used multiple times.
If not used as an instance then the default args and kwargs are used.
-
class
aspectlib.
Return
(value)[source]¶ Instruction for returning a optional value.
If not used as an instance then
None
is returned.
-
class
aspectlib.
Aspect
(advising_function, bind=False)[source]¶ Container for the advice yielding generator. Can be used as a decorator on other function to change behavior according to the advices yielded from the generator.
Parameters: - advising_function (generator function) – A generator function that yields Advices.
- bind (bool) – A convenience flag so you can access the cutpoint function (you’ll get it as an argument).
Usage:
>>> @Aspect ... def my_decorator(*args, **kwargs): ... print("Got called with args: %s kwargs: %s" % (args, kwargs)) ... result = yield ... print(" ... and the result is: %s" % (result,)) >>> @my_decorator ... def foo(a, b, c=1): ... print((a, b, c)) >>> foo(1, 2, c=3) Got called with args: (1, 2) kwargs: {'c': 3} (1, 2, 3) ... and the result is: None
Normally you don’t have access to the cutpoints (the functions you’re going to use the aspect/decorator on) because you don’t and should not call them directly. There are situations where you’d want to get the name or other data from the function. This is where you use the
bind=True
option:>>> @Aspect(bind=True) ... def my_decorator(cutpoint, *args, **kwargs): ... print("`%s` got called with args: %s kwargs: %s" % (cutpoint.__name__, args, kwargs)) ... result = yield ... print(" ... and the result is: %s" % (result,)) >>> @my_decorator ... def foo(a, b, c=1): ... print((a, b, c)) >>> foo(1, 2, c=3) `foo` got called with args: (1, 2) kwargs: {'c': 3} (1, 2, 3) ... and the result is: None
You can use these advices:
Proceed
orNone
- Calls the wrapped function with the default arguments. The yield returns the function’s return value or raises an exception. Can be used multiple times (will call the function multiple times).Proceed
(*args, **kwargs)
- Same as above but with different arguments.Return
- Makes the wrapper returnNone
instead. Ifaspectlib.Proceed
was never used then the wrapped function is not called. After this the generator is closed.Return
(value)
- Same as above but returns the givenvalue
instead ofNone
.raise exception
- Makes the wrapper raise an exception.
Note
The Aspect will correctly handle generators and coroutines (consume them, capture result).
Example:
>>> from aspectlib import Aspect >>> @Aspect ... def log_errors(*args, **kwargs): ... try: ... yield ... except Exception as exc: ... print("Raised %r for %s/%s" % (exc, args, kwargs)) ... raise
Will work as expected with generators (and coroutines):
>>> @log_errors ... def broken_generator(): ... yield 1 ... raise RuntimeError() >>> from pytest import raises >>> raises(RuntimeError, lambda: list(broken_generator())) Raised RuntimeError() for ()/{} ... >>> @log_errors ... def broken_function(): ... raise RuntimeError() >>> raises(RuntimeError, broken_function) Raised RuntimeError() for ()/{} ...
And it will handle results:
>>> from aspectlib import Aspect >>> @Aspect ... def log_results(*args, **kwargs): ... try: ... value = yield ... except Exception as exc: ... print("Raised %r for %s/%s" % (exc, args, kwargs)) ... raise ... else: ... print("Returned %r for %s/%s" % (value, args, kwargs)) >>> @log_results ... def weird_function(): ... yield 1 ... raise StopIteration('foobar') # in Python 3 it's the same as: return 'foobar' >>> list(weird_function()) Returned 'foobar' for ()/{} [1]
-
class
aspectlib.
Rollback
(rollback=None)[source]¶ When called, rollbacks all the patches and changes the
weave()
has done.-
rollback
(*_)¶ Alias of
__exit__
.
-
__call__
(*_)¶ Alias of
__exit__
.
-
-
aspectlib.
ALL_METHODS
Weave all magic methods. Can be used as the value for methods argument in weave.¶ Compiled regular expression objects
-
aspectlib.
NORMAL_METHODS
Only weave non-magic methods. Can be used as the value for methods argument in weave.¶ Compiled regular expression objects
-
aspectlib.
weave
(target, aspect[, subclasses=True, methods=NORMAL_METHODS, lazy=False, aliases=True])[source]¶ Send a message to a recipient
Parameters: - target (string, class, instance, function or builtin) – The object to weave.
- aspects (
aspectlib.Aspect
, function decorator or list of) – The aspects to apply to the object. - subclasses (bool) – If
True
, subclasses of target are weaved. Only available for classes - aliases (bool) – If
True
, aliases of target are replaced. - lazy (bool) – If
True
only target’s__init__
method is patched, the rest of the methods are patched after__init__
is called. Only available for classes. - methods (list or regex or string) – Methods from target to patch. Only available for classes
Returns: aspectlib.Rollback – An object that can rollback the patches.
Raises: TypeError
– If target is a unacceptable object, or the specified options are not available for that type of object.Changed in version 0.4.0: Replaced only_methods, skip_methods, skip_magicmethods options with methods. Renamed on_init option to lazy. Added aliases option. Replaced skip_subclasses option with subclasses.