1import unittest
2
3
4class TestLoadAttrCache(unittest.TestCase):
5    def test_descriptor_added_after_optimization(self):
6        class Descriptor:
7            pass
8
9        class C:
10            def __init__(self):
11                self.x = 1
12            x = Descriptor()
13
14        def f(o):
15            return o.x
16
17        o = C()
18        for i in range(1025):
19            assert f(o) == 1
20
21        Descriptor.__get__ = lambda self, instance, value: 2
22        Descriptor.__set__ = lambda *args: None
23
24        self.assertEqual(f(o), 2)
25
26    def test_metaclass_descriptor_added_after_optimization(self):
27        class Descriptor:
28            pass
29
30        class Metaclass(type):
31            attribute = Descriptor()
32
33        class Class(metaclass=Metaclass):
34            attribute = True
35
36        def __get__(self, instance, owner):
37            return False
38
39        def __set__(self, instance, value):
40            return None
41
42        def f():
43            return Class.attribute
44
45        for _ in range(1025):
46            self.assertTrue(f())
47
48        Descriptor.__get__ = __get__
49        Descriptor.__set__ = __set__
50
51        for _ in range(1025):
52            self.assertFalse(f())
53
54    def test_metaclass_descriptor_shadows_class_attribute(self):
55        class Metaclass(type):
56            @property
57            def attribute(self):
58                return True
59
60        class Class(metaclass=Metaclass):
61            attribute = False
62
63        def f():
64            return Class.attribute
65
66        for _ in range(1025):
67            self.assertTrue(f())
68
69    def test_metaclass_set_descriptor_after_optimization(self):
70        class Metaclass(type):
71            pass
72
73        class Class(metaclass=Metaclass):
74            attribute = True
75
76        @property
77        def attribute(self):
78            return False
79
80        def f():
81            return Class.attribute
82
83        for _ in range(1025):
84            self.assertTrue(f())
85
86        Metaclass.attribute = attribute
87
88        for _ in range(1025):
89            self.assertFalse(f())
90
91    def test_metaclass_del_descriptor_after_optimization(self):
92        class Metaclass(type):
93            @property
94            def attribute(self):
95                return True
96
97        class Class(metaclass=Metaclass):
98            attribute = False
99
100        def f():
101            return Class.attribute
102
103        for _ in range(1025):
104            self.assertTrue(f())
105
106        del Metaclass.attribute
107
108        for _ in range(1025):
109            self.assertFalse(f())
110
111    def test_type_descriptor_shadows_attribute_method(self):
112        class Class:
113            mro = None
114
115        def f():
116            return Class.mro
117
118        for _ in range(1025):
119            self.assertIsNone(f())
120
121    def test_type_descriptor_shadows_attribute_member(self):
122        class Class:
123            __base__ = None
124
125        def f():
126            return Class.__base__
127
128        for _ in range(1025):
129            self.assertIs(f(), object)
130
131    def test_type_descriptor_shadows_attribute_getset(self):
132        class Class:
133            __name__ = "Spam"
134
135        def f():
136            return Class.__name__
137
138        for _ in range(1025):
139            self.assertEqual(f(), "Class")
140
141    def test_metaclass_getattribute(self):
142        class Metaclass(type):
143            def __getattribute__(self, name):
144                return True
145
146        class Class(metaclass=Metaclass):
147            attribute = False
148
149        def f():
150            return Class.attribute
151
152        for _ in range(1025):
153            self.assertTrue(f())
154
155    def test_metaclass_swap(self):
156        class OldMetaclass(type):
157            @property
158            def attribute(self):
159                return True
160
161        class NewMetaclass(type):
162            @property
163            def attribute(self):
164                return False
165
166        class Class(metaclass=OldMetaclass):
167            pass
168
169        def f():
170            return Class.attribute
171
172        for _ in range(1025):
173            self.assertTrue(f())
174
175        Class.__class__ = NewMetaclass
176
177        for _ in range(1025):
178            self.assertFalse(f())
179
180    def test_load_shadowing_slot_should_raise_type_error(self):
181        class Class:
182            __slots__ = ("slot",)
183
184        class Sneaky:
185            __slots__ = ("shadowed",)
186            shadowing = Class.slot
187
188        def f(o):
189            o.shadowing
190
191        o = Sneaky()
192        o.shadowed = 42
193
194        for _ in range(1025):
195            with self.assertRaises(TypeError):
196                f(o)
197
198    def test_store_shadowing_slot_should_raise_type_error(self):
199        class Class:
200            __slots__ = ("slot",)
201
202        class Sneaky:
203            __slots__ = ("shadowed",)
204            shadowing = Class.slot
205
206        def f(o):
207            o.shadowing = 42
208
209        o = Sneaky()
210
211        for _ in range(1025):
212            with self.assertRaises(TypeError):
213                f(o)
214
215    def test_load_borrowed_slot_should_not_crash(self):
216        class Class:
217            __slots__ = ("slot",)
218
219        class Sneaky:
220            borrowed = Class.slot
221
222        def f(o):
223            o.borrowed
224
225        o = Sneaky()
226
227        for _ in range(1025):
228            with self.assertRaises(TypeError):
229                f(o)
230
231    def test_store_borrowed_slot_should_not_crash(self):
232        class Class:
233            __slots__ = ("slot",)
234
235        class Sneaky:
236            borrowed = Class.slot
237
238        def f(o):
239            o.borrowed = 42
240
241        o = Sneaky()
242
243        for _ in range(1025):
244            with self.assertRaises(TypeError):
245                f(o)
246
247
248class TestLoadMethodCache(unittest.TestCase):
249    def test_descriptor_added_after_optimization(self):
250        class Descriptor:
251            pass
252
253        class Class:
254            attribute = Descriptor()
255
256        def __get__(self, instance, owner):
257            return lambda: False
258
259        def __set__(self, instance, value):
260            return None
261
262        def attribute():
263            return True
264
265        instance = Class()
266        instance.attribute = attribute
267
268        def f():
269            return instance.attribute()
270
271        for _ in range(1025):
272            self.assertTrue(f())
273
274        Descriptor.__get__ = __get__
275        Descriptor.__set__ = __set__
276
277        for _ in range(1025):
278            self.assertFalse(f())
279
280    def test_metaclass_descriptor_added_after_optimization(self):
281        class Descriptor:
282            pass
283
284        class Metaclass(type):
285            attribute = Descriptor()
286
287        class Class(metaclass=Metaclass):
288            def attribute():
289                return True
290
291        def __get__(self, instance, owner):
292            return lambda: False
293
294        def __set__(self, instance, value):
295            return None
296
297        def f():
298            return Class.attribute()
299
300        for _ in range(1025):
301            self.assertTrue(f())
302
303        Descriptor.__get__ = __get__
304        Descriptor.__set__ = __set__
305
306        for _ in range(1025):
307            self.assertFalse(f())
308
309    def test_metaclass_descriptor_shadows_class_attribute(self):
310        class Metaclass(type):
311            @property
312            def attribute(self):
313                return lambda: True
314
315        class Class(metaclass=Metaclass):
316            def attribute():
317                return False
318
319        def f():
320            return Class.attribute()
321
322        for _ in range(1025):
323            self.assertTrue(f())
324
325    def test_metaclass_set_descriptor_after_optimization(self):
326        class Metaclass(type):
327            pass
328
329        class Class(metaclass=Metaclass):
330            def attribute():
331                return True
332
333        @property
334        def attribute(self):
335            return lambda: False
336
337        def f():
338            return Class.attribute()
339
340        for _ in range(1025):
341            self.assertTrue(f())
342
343        Metaclass.attribute = attribute
344
345        for _ in range(1025):
346            self.assertFalse(f())
347
348    def test_metaclass_del_descriptor_after_optimization(self):
349        class Metaclass(type):
350            @property
351            def attribute(self):
352                return lambda: True
353
354        class Class(metaclass=Metaclass):
355            def attribute():
356                return False
357
358        def f():
359            return Class.attribute()
360
361        for _ in range(1025):
362            self.assertTrue(f())
363
364        del Metaclass.attribute
365
366        for _ in range(1025):
367            self.assertFalse(f())
368
369    def test_type_descriptor_shadows_attribute_method(self):
370        class Class:
371            def mro():
372                return ["Spam", "eggs"]
373
374        def f():
375            return Class.mro()
376
377        for _ in range(1025):
378            self.assertEqual(f(), ["Spam", "eggs"])
379
380    def test_type_descriptor_shadows_attribute_member(self):
381        class Class:
382            def __base__():
383                return "Spam"
384
385        def f():
386            return Class.__base__()
387
388        for _ in range(1025):
389            self.assertNotEqual(f(), "Spam")
390
391    def test_metaclass_getattribute(self):
392        class Metaclass(type):
393            def __getattribute__(self, name):
394                return lambda: True
395
396        class Class(metaclass=Metaclass):
397            def attribute():
398                return False
399
400        def f():
401            return Class.attribute()
402
403        for _ in range(1025):
404            self.assertTrue(f())
405
406    def test_metaclass_swap(self):
407        class OldMetaclass(type):
408            @property
409            def attribute(self):
410                return lambda: True
411
412        class NewMetaclass(type):
413            @property
414            def attribute(self):
415                return lambda: False
416
417        class Class(metaclass=OldMetaclass):
418            pass
419
420        def f():
421            return Class.attribute()
422
423        for _ in range(1025):
424            self.assertTrue(f())
425
426        Class.__class__ = NewMetaclass
427
428        for _ in range(1025):
429            self.assertFalse(f())
430
431
432if __name__ == "__main__":
433    import unittest
434    unittest.main()
435