mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	[3.11] GH-94822: Don't specialize when metaclasses are involved (GH-94892) (GH-94980)
(cherry picked from commit daf68ba92f)
Co-authored-by: Brandt Bucher <brandtbucher@microsoft.com>
			
			
This commit is contained in:
		
							parent
							
								
									a5c8cecf29
								
							
						
					
					
						commit
						eda2f90094
					
				
					 3 changed files with 351 additions and 6 deletions
				
			
		|  | @ -1,5 +1,6 @@ | |||
| import unittest | ||||
| 
 | ||||
| 
 | ||||
| class TestLoadAttrCache(unittest.TestCase): | ||||
|     def test_descriptor_added_after_optimization(self): | ||||
|         class Descriptor: | ||||
|  | @ -21,3 +22,346 @@ def f(o): | |||
|         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()) | ||||
| 
 | ||||
| 
 | ||||
| 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() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brandt Bucher
						Brandt Bucher