1
|
|
|
import functools |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
class ContextMethodDecorator(): |
5
|
|
|
"""A helper ContextManager decorating a method with a custom function.""" |
6
|
|
|
|
7
|
|
|
def __init__(self, classx, method_name, decorator_func): |
8
|
|
|
""" |
9
|
|
|
Create a new context manager decorating a function within its scope. |
10
|
|
|
|
11
|
|
|
This is a helper Context Manager that decorates a method of a class |
12
|
|
|
with a custom function. |
13
|
|
|
The decoration is only valid within the scope. |
14
|
|
|
:param classx: A class (object) |
15
|
|
|
:param method_name A string name of the method to be decorated |
16
|
|
|
:param decorator_func: The decorator function is responsible |
17
|
|
|
for calling the original method. |
18
|
|
|
The signature should be: func(instance, original_method, |
19
|
|
|
original_args, original_kwargs) |
20
|
|
|
when called, instance refers to an instance of classx and the |
21
|
|
|
original_method refers to the original method object which can be |
22
|
|
|
called. |
23
|
|
|
args and kwargs are arguments passed to the method |
24
|
|
|
|
25
|
|
|
""" |
26
|
|
|
self.method_name = method_name |
27
|
|
|
self.decorator_func = decorator_func |
28
|
|
|
self.classx = classx |
29
|
|
|
self.patched_by_me = False |
30
|
|
|
|
31
|
|
|
def __enter__(self): |
32
|
|
|
|
33
|
|
|
self.original_method = getattr(self.classx, self.method_name) |
34
|
|
|
if not getattr(self.original_method, |
35
|
|
|
"sacred_patched%s" % self.__class__.__name__, False): |
36
|
|
|
@functools.wraps(self.original_method) |
37
|
|
|
def decorated(instance, *args, **kwargs): |
38
|
|
|
return self.decorator_func(instance, |
39
|
|
|
self.original_method, args, |
40
|
|
|
kwargs) |
41
|
|
|
|
42
|
|
|
setattr(self.classx, self.method_name, decorated) |
43
|
|
|
setattr(decorated, |
44
|
|
|
"sacred_patched%s" % self.__class__.__name__, True) |
45
|
|
|
self.patched_by_me = True |
46
|
|
|
|
47
|
|
|
def __exit__(self, type, value, traceback): |
48
|
|
|
if self.patched_by_me: |
49
|
|
|
# Restore original function |
50
|
|
|
setattr(self.classx, self.method_name, self.original_method) |
51
|
|
|
|