import unittest class TestLoadSuperAttrCache(unittest.TestCase): def test_descriptor_not_double_executed_on_spec_fail(self): calls = [] class Descriptor: def __get__(self, instance, owner): calls.append((instance, owner)) return lambda: 1 class C: d = Descriptor() class D(C): def f(self): return super().d() d = D() self.assertEqual(d.f(), 1) # warmup calls.clear() self.assertEqual(d.f(), 1) # try to specialize self.assertEqual(calls, [(d, D)]) class TestLoadAttrCache(unittest.TestCase): def test_descriptor_added_after_optimization(self): class Descriptor: pass class C: def __init__(self): self.x = 1 x = Descriptor() def f(o): return o.x o = C() for i in range(1025): assert f(o) == 1 Descriptor.__get__ = lambda self, instance, value: 2 Descriptor.__set__ = lambda *args: None self.assertEqual(f(o), 2) def test_metaclass_descriptor_added_after_optimization(self): class Descriptor: pass class Metaclass(type): attribute = Descriptor() class Class(metaclass=Metaclass): attribute = True def __get__(self, instance, owner): return False def __set__(self, instance, value): return None def f(): return Class.attribute for _ in range(1025): self.assertTrue(f()) Descriptor.__get__ = __get__ Descriptor.__set__ = __set__ for _ in range(1025): self.assertFalse(f()) def test_metaclass_descriptor_shadows_class_attribute(self): class Metaclass(type): @property def attribute(self): return True class Class(metaclass=Metaclass): attribute = False def f(): return Class.attribute for _ in range(1025): self.assertTrue(f()) def test_metaclass_set_descriptor_after_optimization(self): class Metaclass(type): pass class Class(metaclass=Metaclass): attribute = True @property def attribute(self): return False def f(): return Class.attribute for _ in range(1025): self.assertTrue(f()) Metaclass.attribute = attribute for _ in range(1025): self.assertFalse(f()) def test_metaclass_del_descriptor_after_optimization(self): class Metaclass(type): @property def attribute(self): return True class Class(metaclass=Metaclass): attribute = False def f(): return Class.attribute for _ in range(1025): self.assertTrue(f()) del Metaclass.attribute for _ in range(1025): self.assertFalse(f()) def test_type_descriptor_shadows_attribute_method(self): class Class: mro = None def f(): return Class.mro for _ in range(1025): self.assertIsNone(f()) def test_type_descriptor_shadows_attribute_member(self): class Class: __base__ = None def f(): return Class.__base__ for _ in range(1025): self.assertIs(f(), object) def test_type_descriptor_shadows_attribute_getset(self): class Class: __name__ = "Spam" def f(): return Class.__name__ for _ in range(1025): self.assertEqual(f(), "Class") def test_metaclass_getattribute(self): class Metaclass(type): def __getattribute__(self, name): return True class Class(metaclass=Metaclass): attribute = False def f(): return Class.attribute for _ in range(1025): self.assertTrue(f()) def test_metaclass_swap(self): class OldMetaclass(type): @property def attribute(self): return True class NewMetaclass(type): @property def attribute(self): return False class Class(metaclass=OldMetaclass): pass def f(): return Class.attribute for _ in range(1025): self.assertTrue(f()) Class.__class__ = NewMetaclass for _ in range(1025): self.assertFalse(f()) def test_load_shadowing_slot_should_raise_type_error(self): class Class: __slots__ = ("slot",) class Sneaky: __slots__ = ("shadowed",) shadowing = Class.slot def f(o): o.shadowing o = Sneaky() o.shadowed = 42 for _ in range(1025): with self.assertRaises(TypeError): f(o) def test_store_shadowing_slot_should_raise_type_error(self): class Class: __slots__ = ("slot",) class Sneaky: __slots__ = ("shadowed",) shadowing = Class.slot def f(o): o.shadowing = 42 o = Sneaky() for _ in range(1025): with self.assertRaises(TypeError): f(o) def test_load_borrowed_slot_should_not_crash(self): class Class: __slots__ = ("slot",) class Sneaky: borrowed = Class.slot def f(o): o.borrowed o = Sneaky() for _ in range(1025): with self.assertRaises(TypeError): f(o) def test_store_borrowed_slot_should_not_crash(self): class Class: __slots__ = ("slot",) class Sneaky: borrowed = Class.slot def f(o): o.borrowed = 42 o = Sneaky() for _ in range(1025): with self.assertRaises(TypeError): f(o) class TestLoadMethodCache(unittest.TestCase): def test_descriptor_added_after_optimization(self): class Descriptor: pass class Class: attribute = Descriptor() def __get__(self, instance, owner): return lambda: False def __set__(self, instance, value): return None def attribute(): return True instance = Class() instance.attribute = attribute def f(): return instance.attribute() for _ in range(1025): self.assertTrue(f()) Descriptor.__get__ = __get__ Descriptor.__set__ = __set__ for _ in range(1025): self.assertFalse(f()) def test_metaclass_descriptor_added_after_optimization(self): class Descriptor: pass class Metaclass(type): attribute = Descriptor() class Class(metaclass=Metaclass): def attribute(): return True def __get__(self, instance, owner): return lambda: False def __set__(self, instance, value): return None def f(): return Class.attribute() for _ in range(1025): self.assertTrue(f()) Descriptor.__get__ = __get__ Descriptor.__set__ = __set__ for _ in range(1025): self.assertFalse(f()) def test_metaclass_descriptor_shadows_class_attribute(self): class Metaclass(type): @property def attribute(self): return lambda: True class Class(metaclass=Metaclass): def attribute(): return False def f(): return Class.attribute() for _ in range(1025): self.assertTrue(f()) def test_metaclass_set_descriptor_after_optimization(self): class Metaclass(type): pass class Class(metaclass=Metaclass): def attribute(): return True @property def attribute(self): return lambda: False def f(): return Class.attribute() for _ in range(1025): self.assertTrue(f()) Metaclass.attribute = attribute for _ in range(1025): self.assertFalse(f()) def test_metaclass_del_descriptor_after_optimization(self): class Metaclass(type): @property def attribute(self): return lambda: True class Class(metaclass=Metaclass): def attribute(): return False def f(): return Class.attribute() for _ in range(1025): self.assertTrue(f()) del Metaclass.attribute for _ in range(1025): self.assertFalse(f()) def test_type_descriptor_shadows_attribute_method(self): class Class: def mro(): return ["Spam", "eggs"] def f(): return Class.mro() for _ in range(1025): self.assertEqual(f(), ["Spam", "eggs"]) def test_type_descriptor_shadows_attribute_member(self): class Class: def __base__(): return "Spam" def f(): return Class.__base__() for _ in range(1025): self.assertNotEqual(f(), "Spam") def test_metaclass_getattribute(self): class Metaclass(type): def __getattribute__(self, name): return lambda: True class Class(metaclass=Metaclass): def attribute(): return False def f(): return Class.attribute() for _ in range(1025): self.assertTrue(f()) def test_metaclass_swap(self): class OldMetaclass(type): @property def attribute(self): return lambda: True class NewMetaclass(type): @property def attribute(self): return lambda: False class Class(metaclass=OldMetaclass): pass def f(): return Class.attribute() for _ in range(1025): self.assertTrue(f()) Class.__class__ = NewMetaclass for _ in range(1025): self.assertFalse(f()) if __name__ == "__main__": import unittest unittest.main()