forked from Suor/funcy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_objects.py
156 lines (113 loc) · 2.73 KB
/
test_objects.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import sys
import pytest
from funcy.objects import *
from funcy import suppress
### @cached_property
def test_cached_property():
calls = [0]
class A(object):
@cached_property
def prop(self):
calls[0] += 1
return 7
a = A()
assert a.prop == 7
assert a.prop == 7
assert calls == [1]
a.prop = 42
assert a.prop == 42
del a.prop
assert a.prop == 7
assert calls == [2]
def test_cached_property_doc():
class A(object):
@cached_property
def prop(self):
"prop doc"
return 7
assert A.prop.__doc__ == "prop doc"
def test_cached_readonly():
class A(object):
@cached_readonly
def prop(self):
return 7
a = A()
assert a.prop == 7
with pytest.raises(AttributeError):
a.prop = 8
def test_wrap_prop():
calls = []
# Not using @contextmanager to not make this a decorator
class Manager:
def __init__(self, name):
self.name = name
def __enter__(self):
calls.append(self.name)
return self
def __exit__(self, *args):
pass
class A(object):
@wrap_prop(Manager('p'))
@property
def prop(self):
return 1
@wrap_prop(Manager('cp'))
@cached_property
def cached_prop(self):
return 1
a = A()
assert a.prop and calls == ['p']
assert a.prop and calls == ['p', 'p']
assert a.cached_prop and calls == ['p', 'p', 'cp']
assert a.cached_prop and calls == ['p', 'p', 'cp']
# Wrap __set__ for data props
a = A()
calls[:] = []
with suppress(AttributeError):
a.prop = 2
assert calls == ['p']
# Do not wrap __set__ for non-data props
a.cached_property = 2
assert calls == ['p']
### Monkey tests
def test_monkey():
class A(object):
def f(self):
return 7
@monkey(A)
def f(self):
return f.original(self) * 6
assert A().f() == 42
def test_monkey_with_name():
class A(object):
def f(self):
return 7
@monkey(A, name='f')
def g(self):
return g.original(self) * 6
assert A().f() == 42
def test_monkey_property():
class A(object):
pass
@monkey(A)
@property
def prop(self):
return 42
assert A().prop == 42
def f(x):
return x
def test_monkey_module():
this_module = sys.modules[__name__]
@monkey(this_module)
def f(x):
return f.original(x) * 2
assert f(21) == 42
def test_lazy_object():
class A(object):
x = 42
def __init__(self):
log.append('init')
log = []
a = LazyObject(A)
assert not log
assert a.x == 42