-
Notifications
You must be signed in to change notification settings - Fork 20
/
pretend.py
117 lines (94 loc) · 2.82 KB
/
pretend.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import functools
MAGIC_METHODS = frozenset(
[
"__iter__",
"__next__",
"__len__",
"__contains__",
"__getitem__",
"__setitem__",
"__delitem__",
"__enter__",
"__exit__",
"__lt__",
"__le__",
"__eq__",
"__ne__",
"__gt__",
"__ge__",
"__add__",
"__and__",
"__divmod__",
"__floordiv__",
"__lshift__",
"__mod__",
"__mul__",
"__or__",
"__pow__",
"__rshift__",
"__sub__",
"__truediv__",
"__xor__",
"__bool__",
"__call__",
"__repr__",
]
)
def _build_magic_dispatcher(method):
def inner(self, *args, **kwargs):
return self.__dict__[method](*args, **kwargs)
inner.__name__ = method
return inner
class stub(object):
_classes_cache = {}
def __new__(cls, **kwargs):
magic_methods_present = MAGIC_METHODS.intersection(kwargs)
if magic_methods_present not in cls._classes_cache:
attrs = {
method: _build_magic_dispatcher(method)
for method in magic_methods_present
}
attrs["__module__"] = cls.__module__
cls._classes_cache[magic_methods_present] = type("stub", (cls,), attrs)
new_cls = cls._classes_cache[magic_methods_present]
return super(stub, new_cls).__new__(new_cls)
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
return "<stub(%s)>" % ", ".join(
"%s=%r" % (key, val) for key, val in self.__dict__.items()
)
def raiser(exc):
if not (
isinstance(exc, BaseException)
or isinstance(exc, type)
and issubclass(exc, BaseException)
):
raise TypeError("exc must be either an exception instance or class.")
def inner(*args, **kwargs):
raise exc
return inner
class call(object):
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def __eq__(self, other):
if not isinstance(other, call):
return NotImplemented
return self.args == other.args and self.kwargs == other.kwargs
def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash((self.args, frozenset(self.kwargs.items())))
def __repr__(self):
args = ", ".join(map(repr, self.args))
kwargs = ", ".join("%s=%r" % (k, v) for k, v in self.kwargs.items())
comma = ", " if args and kwargs else ""
return "<call(%s%s%s)>" % (args, comma, kwargs)
def call_recorder(func):
@functools.wraps(func)
def inner(*args, **kwargs):
inner.calls.append(call(*args, **kwargs))
return func(*args, **kwargs)
inner.calls = []
return inner