| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  | import copy | 
					
						
							|  |  |  | import pickle | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  | import dis | 
					
						
							|  |  |  | import threading | 
					
						
							|  |  |  | import types | 
					
						
							| 
									
										
										
										
											2020-11-05 09:23:15 +00:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | from test.support import (threading_helper, check_impl_detail, | 
					
						
							|  |  |  |                           requires_specialization, requires_specialization_ft, | 
					
						
							| 
									
										
										
										
											2025-01-31 02:50:54 -08:00
										 |  |  |                           cpython_only, requires_jit_disabled, reset_code) | 
					
						
							| 
									
										
										
										
											2024-04-03 15:11:36 +02:00
										 |  |  | from test.support.import_helper import import_module | 
					
						
							| 
									
										
										
										
											2023-09-22 23:51:58 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Skip this module on other interpreters, it is cpython specific: | 
					
						
							|  |  |  | if check_impl_detail(cpython=False): | 
					
						
							|  |  |  |     raise unittest.SkipTest('implementation detail specific to cpython') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-03 15:11:36 +02:00
										 |  |  | _testinternalcapi = import_module("_testinternalcapi") | 
					
						
							| 
									
										
										
										
											2020-11-05 09:23:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-28 12:54:55 -07:00
										 |  |  | def have_dict_key_versions(): | 
					
						
							|  |  |  |     # max version value that can be stored in the load global cache. This is | 
					
						
							|  |  |  |     # determined by the type of module_keys_version and builtin_keys_version | 
					
						
							|  |  |  |     # in _PyLoadGlobalCache, uint16_t. | 
					
						
							|  |  |  |     max_version = 1<<16 | 
					
						
							|  |  |  |     # use a wide safety margin (use only half of what's available) | 
					
						
							|  |  |  |     limit = max_version // 2 | 
					
						
							|  |  |  |     return _testinternalcapi.get_next_dict_keys_version() < limit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  | class TestBase(unittest.TestCase): | 
					
						
							|  |  |  |     def assert_specialized(self, f, opname): | 
					
						
							|  |  |  |         instructions = dis.get_instructions(f, adaptive=True) | 
					
						
							|  |  |  |         opnames = {instruction.opname for instruction in instructions} | 
					
						
							|  |  |  |         self.assertIn(opname, opnames) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  |     def assert_no_opcode(self, f, opname): | 
					
						
							|  |  |  |         instructions = dis.get_instructions(f, adaptive=True) | 
					
						
							|  |  |  |         opnames = {instruction.opname for instruction in instructions} | 
					
						
							|  |  |  |         self.assertNotIn(opname, opnames) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-25 11:45:51 -06:00
										 |  |  | 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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD - 1): | 
					
						
							|  |  |  |             self.assertEqual(d.f(), 1)  # warmup | 
					
						
							| 
									
										
										
										
											2023-04-25 11:45:51 -06:00
										 |  |  |         calls.clear() | 
					
						
							|  |  |  |         self.assertEqual(d.f(), 1)  # try to specialize | 
					
						
							|  |  |  |         self.assertEqual(calls, [(d, D)]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 09:23:15 +00:00
										 |  |  | 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() | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2020-11-05 09:23:15 +00:00
										 |  |  |             assert f(o) == 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Descriptor.__get__ = lambda self, instance, value: 2 | 
					
						
							|  |  |  |         Descriptor.__set__ = lambda *args: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assertEqual(f(o), 2) | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Descriptor.__get__ = __get__ | 
					
						
							|  |  |  |         Descriptor.__set__ = __set__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Metaclass.attribute = attribute | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         del Metaclass.attribute | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertFalse(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_descriptor_shadows_attribute_method(self): | 
					
						
							|  |  |  |         class Class: | 
					
						
							|  |  |  |             mro = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             return Class.mro | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertIsNone(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_descriptor_shadows_attribute_member(self): | 
					
						
							|  |  |  |         class Class: | 
					
						
							|  |  |  |             __base__ = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             return Class.__base__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertIs(f(), object) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_descriptor_shadows_attribute_getset(self): | 
					
						
							|  |  |  |         class Class: | 
					
						
							|  |  |  |             __name__ = "Spam" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             return Class.__name__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Class.__class__ = NewMetaclass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertFalse(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-10 03:50:34 -08:00
										 |  |  |     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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-11-10 03:50:34 -08:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-11-10 03:50:34 -08:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-11-10 03:50:34 -08:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-11-10 03:50:34 -08:00
										 |  |  |             with self.assertRaises(TypeError): | 
					
						
							|  |  |  |                 f(o) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Descriptor.__get__ = __get__ | 
					
						
							|  |  |  |         Descriptor.__set__ = __set__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Descriptor.__get__ = __get__ | 
					
						
							|  |  |  |         Descriptor.__set__ = __set__ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Metaclass.attribute = attribute | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         del Metaclass.attribute | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertFalse(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_descriptor_shadows_attribute_method(self): | 
					
						
							|  |  |  |         class Class: | 
					
						
							|  |  |  |             def mro(): | 
					
						
							|  |  |  |                 return ["Spam", "eggs"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             return Class.mro() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertEqual(f(), ["Spam", "eggs"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_type_descriptor_shadows_attribute_member(self): | 
					
						
							|  |  |  |         class Class: | 
					
						
							|  |  |  |             def __base__(): | 
					
						
							|  |  |  |                 return "Spam" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             return Class.__base__() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             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() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertTrue(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Class.__class__ = NewMetaclass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  |             self.assertFalse(f()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-03 11:20:20 -08:00
										 |  |  | class InitTakesArg: | 
					
						
							|  |  |  |     def __init__(self, arg): | 
					
						
							|  |  |  |         self.arg = arg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  | class TestCallCache(TestBase): | 
					
						
							| 
									
										
										
										
											2023-06-16 11:01:15 -07:00
										 |  |  |     def test_too_many_defaults_0(self): | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.__defaults__ = (None,) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-06-16 11:01:15 -07:00
										 |  |  |             f() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_too_many_defaults_1(self): | 
					
						
							|  |  |  |         def f(x): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.__defaults__ = (None, None) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-06-16 11:01:15 -07:00
										 |  |  |             f(None) | 
					
						
							|  |  |  |             f() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_too_many_defaults_2(self): | 
					
						
							|  |  |  |         def f(x, y): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         f.__defaults__ = (None, None, None) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-06-16 11:01:15 -07:00
										 |  |  |             f(None, None) | 
					
						
							|  |  |  |             f(None) | 
					
						
							|  |  |  |             f() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-28 16:10:51 -08:00
										 |  |  |     @requires_jit_disabled | 
					
						
							| 
									
										
										
										
											2024-12-03 11:20:20 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  |     def test_assign_init_code(self): | 
					
						
							| 
									
										
										
										
											2024-12-19 13:03:14 -08:00
										 |  |  |         class MyClass: | 
					
						
							|  |  |  |             def __init__(self): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  |         def instantiate(): | 
					
						
							|  |  |  |             return MyClass() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Trigger specialization | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  |             instantiate() | 
					
						
							|  |  |  |         self.assert_specialized(instantiate, "CALL_ALLOC_AND_ENTER_INIT") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def count_args(self, *args): | 
					
						
							|  |  |  |             self.num_args = len(args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Set MyClass.__init__.__code__ to a code object that uses different | 
					
						
							|  |  |  |         # args | 
					
						
							|  |  |  |         MyClass.__init__.__code__ = count_args.__code__ | 
					
						
							|  |  |  |         instantiate() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-28 16:10:51 -08:00
										 |  |  |     @requires_jit_disabled | 
					
						
							| 
									
										
										
										
											2024-12-03 11:20:20 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_push_init_frame_fails(self): | 
					
						
							|  |  |  |         def instantiate(): | 
					
						
							|  |  |  |             return InitTakesArg() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-03 11:20:20 -08:00
										 |  |  |             with self.assertRaises(TypeError): | 
					
						
							|  |  |  |                 instantiate() | 
					
						
							|  |  |  |         self.assert_specialized(instantiate, "CALL_ALLOC_AND_ENTER_INIT") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with self.assertRaises(TypeError): | 
					
						
							|  |  |  |             instantiate() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-03 00:36:29 +08:00
										 |  |  |     def test_recursion_check_for_general_calls(self): | 
					
						
							|  |  |  |         def test(default=None): | 
					
						
							|  |  |  |             return test() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         with self.assertRaises(RecursionError): | 
					
						
							|  |  |  |             test() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-10-03 09:58:32 -07:00
										 |  |  |     def test_dont_specialize_custom_vectorcall(self): | 
					
						
							|  |  |  |         def f(): | 
					
						
							|  |  |  |             raise Exception("no way") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         _testinternalcapi.set_vectorcall_nop(f) | 
					
						
							|  |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							|  |  |  |             f() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-16 11:01:15 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  | def make_deferred_ref_count_obj(): | 
					
						
							|  |  |  |     """Create an object that uses deferred reference counting.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Only objects that use deferred refence counting may be stored in inline | 
					
						
							|  |  |  |     caches in free-threaded builds. This constructs a new class named Foo, | 
					
						
							|  |  |  |     which uses deferred reference counting. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return type("Foo", (object,), {}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-28 13:04:59 -07:00
										 |  |  | @threading_helper.requires_working_threading() | 
					
						
							| 
									
										
										
										
											2024-08-22 00:38:04 -07:00
										 |  |  | class TestRacesDoNotCrash(TestBase): | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     # Careful with these. Bigger numbers have a higher chance of catching bugs, | 
					
						
							|  |  |  |     # but you can also burn through a *ton* of type/dict/function versions: | 
					
						
							|  |  |  |     ITEMS = 1000 | 
					
						
							|  |  |  |     LOOPS = 4 | 
					
						
							|  |  |  |     WRITERS = 2 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-28 16:10:51 -08:00
										 |  |  |     @requires_jit_disabled | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def assert_races_do_not_crash( | 
					
						
							|  |  |  |         self, opname, get_items, read, write, *, check_items=False | 
					
						
							|  |  |  |     ): | 
					
						
							|  |  |  |         # This might need a few dozen loops in some cases: | 
					
						
							|  |  |  |         for _ in range(self.LOOPS): | 
					
						
							|  |  |  |             items = get_items() | 
					
						
							|  |  |  |             # Reset: | 
					
						
							|  |  |  |             if check_items: | 
					
						
							|  |  |  |                 for item in items: | 
					
						
							| 
									
										
										
										
											2025-01-31 02:50:54 -08:00
										 |  |  |                     reset_code(item) | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |             else: | 
					
						
							| 
									
										
										
										
											2025-01-31 02:50:54 -08:00
										 |  |  |                 reset_code(read) | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |             # Specialize: | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |                 read(items) | 
					
						
							|  |  |  |             if check_items: | 
					
						
							|  |  |  |                 for item in items: | 
					
						
							|  |  |  |                     self.assert_specialized(item, opname) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 self.assert_specialized(read, opname) | 
					
						
							|  |  |  |             # Create writers: | 
					
						
							|  |  |  |             writers = [] | 
					
						
							|  |  |  |             for _ in range(self.WRITERS): | 
					
						
							|  |  |  |                 writer = threading.Thread(target=write, args=[items]) | 
					
						
							|  |  |  |                 writers.append(writer) | 
					
						
							|  |  |  |             # Run: | 
					
						
							|  |  |  |             for writer in writers: | 
					
						
							|  |  |  |                 writer.start() | 
					
						
							|  |  |  |             read(items)  # BOOM! | 
					
						
							|  |  |  |             for writer in writers: | 
					
						
							|  |  |  |                 writer.join() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-24 02:08:34 +09:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_binary_subscr_getitem(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 __getitem__ = lambda self, item: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							| 
									
										
										
										
											2025-04-28 23:38:29 -07:00
										 |  |  |             for _ in range(self.ITEMS): | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item[None] | 
					
						
							|  |  |  |                 except TypeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.__getitem__ | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 type(item).__getitem__ = lambda self, item: None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |         opname = "BINARY_OP_SUBSCR_GETITEM" | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_binary_subscr_list_int(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = [None] | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item[0] | 
					
						
							|  |  |  |                 except IndexError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.clear() | 
					
						
							|  |  |  |                 item.append(None) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |         opname = "BINARY_OP_SUBSCR_LIST_INT" | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 11:22:21 -08:00
										 |  |  |     @requires_specialization | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_for_iter_gen(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             def g(): | 
					
						
							|  |  |  |                 yield | 
					
						
							|  |  |  |                 yield | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = g() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     for _ in item: | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                 except ValueError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     for _ in item: | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |                 except ValueError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "FOR_ITER_GEN" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 11:22:21 -08:00
										 |  |  |     @requires_specialization | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_for_iter_list(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = [None] | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 for item in item: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.clear() | 
					
						
							|  |  |  |                 item.append(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "FOR_ITER_LIST" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_class(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |                 a = make_deferred_ref_count_obj() | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |                 item.a = make_deferred_ref_count_obj() | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_CLASS" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_load_attr_class_with_metaclass_check(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class Meta(type): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             class C(metaclass=Meta): | 
					
						
							|  |  |  |                 a = make_deferred_ref_count_obj() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 item.a = make_deferred_ref_count_obj() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_CLASS_WITH_METACLASS_CHECK" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_getattribute_overridden(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 __getattribute__ = lambda self, name: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							| 
									
										
										
										
											2025-04-28 23:38:29 -07:00
										 |  |  |             for _ in range(self.ITEMS): | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.__getattribute__ | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 type(item).__getattribute__ = lambda self, name: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_instance_value(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 item.a = None | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.__dict__[None] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_INSTANCE_VALUE" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_method_lazy_dict(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C(Exception): | 
					
						
							|  |  |  |                 m = lambda self: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.m() | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.m | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 type(item).m = lambda self: None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-23 04:26:25 -05:00
										 |  |  |         opname = "LOAD_ATTR_METHOD_LAZY_DICT" | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_method_no_dict(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 __slots__ = () | 
					
						
							|  |  |  |                 m = lambda self: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.m() | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.m | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 type(item).m = lambda self: None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-23 04:26:25 -05:00
										 |  |  |         opname = "LOAD_ATTR_METHOD_NO_DICT" | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_method_with_values(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 m = lambda self: None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.m() | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del item.m | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 type(item).m = lambda self: None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-23 04:26:25 -05:00
										 |  |  |         opname = "LOAD_ATTR_METHOD_WITH_VALUES" | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-13 10:17:16 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_module(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = types.ModuleType("<item>") | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.__name__ | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 d = item.__dict__.copy() | 
					
						
							|  |  |  |                 item.__dict__.clear() | 
					
						
							|  |  |  |                 item.__dict__.update(d) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_MODULE" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_property(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 a = property(lambda self: None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item.a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     del type(item).a | 
					
						
							|  |  |  |                 except AttributeError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  |                 type(item).a = property(lambda self: None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_PROPERTY" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-14 11:56:11 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_load_attr_slot(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 __slots__ = ["a", "b"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for i in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 item.a = i | 
					
						
							|  |  |  |                 item.b = i + self.ITEMS | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.a | 
					
						
							|  |  |  |                 item.b | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.a = 100 | 
					
						
							|  |  |  |                 item.b = 200 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_SLOT" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_attr_with_hint(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 item.a = None | 
					
						
							| 
									
										
										
										
											2023-08-09 12:14:50 -07:00
										 |  |  |                 # Resize into a combined unicode dict: | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |                 for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1): | 
					
						
							| 
									
										
										
										
											2023-08-09 12:14:50 -07:00
										 |  |  |                     setattr(item, f"_{i}", None) | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.a | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.__dict__[None] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_ATTR_WITH_HINT" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 11:22:21 -08:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_load_global_module(self): | 
					
						
							| 
									
										
										
										
											2025-04-28 12:54:55 -07:00
										 |  |  |         if not have_dict_key_versions(): | 
					
						
							|  |  |  |             raise unittest.SkipTest("Low on dict key versions") | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |         def get_items(): | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = eval("lambda: x", {"x": None}) | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.__globals__[None] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "LOAD_GLOBAL_MODULE" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash( | 
					
						
							|  |  |  |             opname, get_items, read, write, check_items=True | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 11:22:21 -08:00
										 |  |  |     @requires_specialization | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_store_attr_instance_value(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.a = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.__dict__[None] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "STORE_ATTR_INSTANCE_VALUE" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-21 11:22:21 -08:00
										 |  |  |     @requires_specialization | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_store_attr_with_hint(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             class C: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = C() | 
					
						
							| 
									
										
										
										
											2023-08-09 12:14:50 -07:00
										 |  |  |                 # Resize into a combined unicode dict: | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |                 for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1): | 
					
						
							| 
									
										
										
										
											2023-08-09 12:14:50 -07:00
										 |  |  |                     setattr(item, f"_{i}", None) | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.a = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.__dict__[None] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "STORE_ATTR_WITH_HINT" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_store_subscr_list_int(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = [None] | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     item[0] = None | 
					
						
							|  |  |  |                 except IndexError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.clear() | 
					
						
							|  |  |  |                 item.append(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "STORE_SUBSCR_LIST_INT" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-19 11:08:17 +09:00
										 |  |  |     @requires_specialization_ft | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  |     def test_unpack_sequence_list(self): | 
					
						
							|  |  |  |         def get_items(): | 
					
						
							|  |  |  |             items = [] | 
					
						
							|  |  |  |             for _ in range(self.ITEMS): | 
					
						
							|  |  |  |                 item = [None] | 
					
						
							|  |  |  |                 items.append(item) | 
					
						
							|  |  |  |             return items | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def read(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     [_] = item | 
					
						
							|  |  |  |                 except ValueError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def write(items): | 
					
						
							|  |  |  |             for item in items: | 
					
						
							|  |  |  |                 item.clear() | 
					
						
							|  |  |  |                 item.append(None) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         opname = "UNPACK_SEQUENCE_LIST" | 
					
						
							|  |  |  |         self.assert_races_do_not_crash(opname, get_items, read, write) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  | class C: | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-29 18:53:32 -08:00
										 |  |  | @requires_specialization | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  | class TestInstanceDict(unittest.TestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setUp(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a, c.b, c.c = 0,0,0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_values_on_instance(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         C().b = 2 | 
					
						
							|  |  |  |         c.c = 3 | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c), | 
					
						
							|  |  |  |             (1, '<NULL>', 3) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_materialization(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         c.b = 2 | 
					
						
							|  |  |  |         c.__dict__ | 
					
						
							| 
									
										
										
										
											2024-04-02 11:59:21 +01:00
										 |  |  |         self.assertEqual(c.__dict__, {"a":1, "b": 2}) | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_dematerialization(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         c.b = 2 | 
					
						
							|  |  |  |         c.__dict__ | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  |             c.a | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c), | 
					
						
							|  |  |  |             (1, 2, '<NULL>') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_dematerialization_multiple_refs(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         c.b = 2 | 
					
						
							|  |  |  |         d = c.__dict__ | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  |             c.a | 
					
						
							|  |  |  |         self.assertIs(c.__dict__, d) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_dematerialization_copy(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         c.b = 2 | 
					
						
							|  |  |  |         c2 = copy.copy(c) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  |             c.a | 
					
						
							|  |  |  |             c2.a | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c), | 
					
						
							|  |  |  |             (1, 2, '<NULL>') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c2), | 
					
						
							|  |  |  |             (1, 2, '<NULL>') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         c3 = copy.deepcopy(c) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  |             c.a | 
					
						
							|  |  |  |             c3.a | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c), | 
					
						
							|  |  |  |             (1, 2, '<NULL>') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         #NOTE -- c3.__dict__ does not de-materialize | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_dematerialization_pickle(self): | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         c.b = 2 | 
					
						
							|  |  |  |         c2 = pickle.loads(pickle.dumps(c)) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  |             c.a | 
					
						
							|  |  |  |             c2.a | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c), | 
					
						
							|  |  |  |             (1, 2, '<NULL>') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c2), | 
					
						
							|  |  |  |             (1, 2, '<NULL>') | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_dict_dematerialization_subclass(self): | 
					
						
							|  |  |  |         class D(dict): pass | 
					
						
							|  |  |  |         c = C() | 
					
						
							|  |  |  |         c.a = 1 | 
					
						
							|  |  |  |         c.b = 2 | 
					
						
							|  |  |  |         c.__dict__ = D(c.__dict__) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2023-08-10 13:34:00 +01:00
										 |  |  |             c.a | 
					
						
							|  |  |  |         self.assertIs( | 
					
						
							|  |  |  |             _testinternalcapi.get_object_dict_values(c), | 
					
						
							|  |  |  |             None | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.assertEqual( | 
					
						
							|  |  |  |             c.__dict__, | 
					
						
							|  |  |  |             {'a':1, 'b':2} | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-24 11:57:02 +01:00
										 |  |  |     def test_125868(self): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def make_special_dict(): | 
					
						
							|  |  |  |             """Create a dictionary an object with a this table:
 | 
					
						
							|  |  |  |             index | key | value | 
					
						
							|  |  |  |             ----- | --- | ----- | 
					
						
							|  |  |  |               0   | 'b' | 'value' | 
					
						
							|  |  |  |               1   | 'b' | NULL | 
					
						
							|  |  |  |             """
 | 
					
						
							|  |  |  |             class A: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             a = A() | 
					
						
							|  |  |  |             a.a = 1 | 
					
						
							|  |  |  |             a.b = 2 | 
					
						
							|  |  |  |             d = a.__dict__.copy() | 
					
						
							|  |  |  |             del d['a'] | 
					
						
							|  |  |  |             del d['b'] | 
					
						
							|  |  |  |             d['b'] = "value" | 
					
						
							|  |  |  |             return d | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class NoInlineAorB: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         for i in range(ord('c'), ord('z')): | 
					
						
							|  |  |  |             setattr(NoInlineAorB(), chr(i), i) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c = NoInlineAorB() | 
					
						
							|  |  |  |         c.a = 0 | 
					
						
							|  |  |  |         c.b = 1 | 
					
						
							|  |  |  |         self.assertFalse(_testinternalcapi.has_inline_values(c)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def f(o, n): | 
					
						
							|  |  |  |             for i in range(n): | 
					
						
							|  |  |  |                 o.b = i | 
					
						
							|  |  |  |         # Prime f to store to dict slot 1 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         f(c, _testinternalcapi.SPECIALIZATION_THRESHOLD) | 
					
						
							| 
									
										
										
										
											2024-10-24 11:57:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         test_obj = NoInlineAorB() | 
					
						
							|  |  |  |         test_obj.__dict__ = make_special_dict() | 
					
						
							|  |  |  |         self.assertEqual(test_obj.b, "value") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #This should set x.b = 0 | 
					
						
							|  |  |  |         f(test_obj, 1) | 
					
						
							|  |  |  |         self.assertEqual(test_obj.b, 0) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-22 15:02:38 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | class TestSpecializer(TestBase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_binary_op(self): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def binary_op_add_int(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  |                 a, b = 1, 2 | 
					
						
							|  |  |  |                 c = a + b | 
					
						
							|  |  |  |                 self.assertEqual(c, 3) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         binary_op_add_int() | 
					
						
							|  |  |  |         self.assert_specialized(binary_op_add_int, "BINARY_OP_ADD_INT") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_add_int, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 22:33:15 +05:00
										 |  |  |         def binary_op_int_non_compact(): | 
					
						
							|  |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							|  |  |  |                 a, b = 10000000000, 1 | 
					
						
							|  |  |  |                 c = a + b | 
					
						
							|  |  |  |                 self.assertEqual(c, 10000000001) | 
					
						
							|  |  |  |                 c = a - b | 
					
						
							|  |  |  |                 self.assertEqual(c, 9999999999) | 
					
						
							|  |  |  |                 c = a * b | 
					
						
							|  |  |  |                 self.assertEqual(c, 10000000000) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_op_int_non_compact() | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_int_non_compact, "BINARY_OP_ADD_INT") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_int_non_compact, "BINARY_OP_SUBTRACT_INT") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_int_non_compact, "BINARY_OP_MULTIPLY_INT") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def binary_op_add_unicode(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  |                 a, b = "foo", "bar" | 
					
						
							|  |  |  |                 c = a + b | 
					
						
							|  |  |  |                 self.assertEqual(c, "foobar") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         binary_op_add_unicode() | 
					
						
							|  |  |  |         self.assert_specialized(binary_op_add_unicode, "BINARY_OP_ADD_UNICODE") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_add_unicode, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-16 15:22:13 +00:00
										 |  |  |         def binary_op_add_extend(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2025-01-16 15:22:13 +00:00
										 |  |  |                 a, b = 6, 3.0 | 
					
						
							|  |  |  |                 c = a + b | 
					
						
							|  |  |  |                 self.assertEqual(c, 9.0) | 
					
						
							|  |  |  |                 c = b + a | 
					
						
							|  |  |  |                 self.assertEqual(c, 9.0) | 
					
						
							|  |  |  |                 c = a - b | 
					
						
							|  |  |  |                 self.assertEqual(c, 3.0) | 
					
						
							|  |  |  |                 c = b - a | 
					
						
							|  |  |  |                 self.assertEqual(c, -3.0) | 
					
						
							|  |  |  |                 c = a * b | 
					
						
							|  |  |  |                 self.assertEqual(c, 18.0) | 
					
						
							|  |  |  |                 c = b * a | 
					
						
							|  |  |  |                 self.assertEqual(c, 18.0) | 
					
						
							|  |  |  |                 c = a / b | 
					
						
							|  |  |  |                 self.assertEqual(c, 2.0) | 
					
						
							|  |  |  |                 c = b / a | 
					
						
							|  |  |  |                 self.assertEqual(c, 0.5) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_op_add_extend() | 
					
						
							|  |  |  |         self.assert_specialized(binary_op_add_extend, "BINARY_OP_EXTEND") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_add_extend, "BINARY_OP") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-19 13:02:49 +02:00
										 |  |  |         def binary_op_zero_division(): | 
					
						
							|  |  |  |             def compactlong_lhs(arg): | 
					
						
							|  |  |  |                 42 / arg | 
					
						
							|  |  |  |             def float_lhs(arg): | 
					
						
							|  |  |  |                 42.0 / arg | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             with self.assertRaises(ZeroDivisionError): | 
					
						
							|  |  |  |                 compactlong_lhs(0) | 
					
						
							|  |  |  |             with self.assertRaises(ZeroDivisionError): | 
					
						
							|  |  |  |                 compactlong_lhs(0.0) | 
					
						
							|  |  |  |             with self.assertRaises(ZeroDivisionError): | 
					
						
							|  |  |  |                 float_lhs(0.0) | 
					
						
							|  |  |  |             with self.assertRaises(ZeroDivisionError): | 
					
						
							|  |  |  |                 float_lhs(0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.assert_no_opcode(compactlong_lhs, "BINARY_OP_EXTEND") | 
					
						
							|  |  |  |             self.assert_no_opcode(float_lhs, "BINARY_OP_EXTEND") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_op_zero_division() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def binary_op_nan(): | 
					
						
							|  |  |  |             def compactlong_lhs(arg): | 
					
						
							|  |  |  |                 return ( | 
					
						
							|  |  |  |                     42 + arg, | 
					
						
							|  |  |  |                     42 - arg, | 
					
						
							|  |  |  |                     42 * arg, | 
					
						
							|  |  |  |                     42 / arg, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             def compactlong_rhs(arg): | 
					
						
							|  |  |  |                 return ( | 
					
						
							|  |  |  |                     arg + 42, | 
					
						
							|  |  |  |                     arg - 42, | 
					
						
							|  |  |  |                     arg * 2, | 
					
						
							|  |  |  |                     arg / 42, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             nan = float('nan') | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							|  |  |  |                 self.assertEqual(compactlong_lhs(1.0), (43.0, 41.0, 42.0, 42.0)) | 
					
						
							|  |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2025-01-19 13:02:49 +02:00
										 |  |  |                 self.assertTrue(all(filter(lambda x: x is nan, compactlong_lhs(nan)))) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							|  |  |  |                 self.assertEqual(compactlong_rhs(42.0), (84.0, 0.0, 84.0, 1.0)) | 
					
						
							|  |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2025-01-19 13:02:49 +02:00
										 |  |  |                 self.assertTrue(all(filter(lambda x: x is nan, compactlong_rhs(nan)))) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             self.assert_no_opcode(compactlong_lhs, "BINARY_OP_EXTEND") | 
					
						
							|  |  |  |             self.assert_no_opcode(compactlong_rhs, "BINARY_OP_EXTEND") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_op_nan() | 
					
						
							| 
									
										
										
										
											2025-01-16 15:22:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 09:28:21 +00:00
										 |  |  |         def binary_op_bitwise_extend(): | 
					
						
							|  |  |  |             for _ in range(100): | 
					
						
							|  |  |  |                 a, b = 2, 7 | 
					
						
							|  |  |  |                 x = a | b | 
					
						
							|  |  |  |                 self.assertEqual(x, 7) | 
					
						
							|  |  |  |                 y = a & b | 
					
						
							|  |  |  |                 self.assertEqual(y, 2) | 
					
						
							|  |  |  |                 z = a ^ b | 
					
						
							|  |  |  |                 self.assertEqual(z, 5) | 
					
						
							|  |  |  |                 a, b = 3, 9 | 
					
						
							|  |  |  |                 a |= b | 
					
						
							|  |  |  |                 self.assertEqual(a, 11) | 
					
						
							|  |  |  |                 a, b = 11, 9 | 
					
						
							|  |  |  |                 a &= b | 
					
						
							|  |  |  |                 self.assertEqual(a, 9) | 
					
						
							|  |  |  |                 a, b = 3, 9 | 
					
						
							|  |  |  |                 a ^= b | 
					
						
							|  |  |  |                 self.assertEqual(a, 10) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_op_bitwise_extend() | 
					
						
							|  |  |  |         self.assert_specialized(binary_op_bitwise_extend, "BINARY_OP_EXTEND") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_op_bitwise_extend, "BINARY_OP") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-03 09:32:26 -08:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_load_super_attr(self): | 
					
						
							|  |  |  |         """Ensure that LOAD_SUPER_ATTR is specialized as expected.""" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class A: | 
					
						
							|  |  |  |             def __init__(self): | 
					
						
							|  |  |  |                 meth = super().__init__ | 
					
						
							|  |  |  |                 super().__init__() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-03 09:32:26 -08:00
										 |  |  |             A() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_ATTR") | 
					
						
							| 
									
										
										
										
											2025-01-23 04:26:25 -05:00
										 |  |  |         self.assert_specialized(A.__init__, "LOAD_SUPER_ATTR_METHOD") | 
					
						
							| 
									
										
										
										
											2024-12-03 09:32:26 -08:00
										 |  |  |         self.assert_no_opcode(A.__init__, "LOAD_SUPER_ATTR") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Temporarily replace super() with something else. | 
					
						
							|  |  |  |         real_super = super | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def fake_super(): | 
					
						
							|  |  |  |             def init(self): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return init | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Force unspecialize | 
					
						
							|  |  |  |         globals()['super'] = fake_super | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             # Should be unspecialized after enough calls. | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_COOLDOWN): | 
					
						
							| 
									
										
										
										
											2024-12-03 09:32:26 -08:00
										 |  |  |                 A() | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             globals()['super'] = real_super | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Ensure the specialized instructions are not present | 
					
						
							|  |  |  |         self.assert_no_opcode(A.__init__, "LOAD_SUPER_ATTR_ATTR") | 
					
						
							|  |  |  |         self.assert_no_opcode(A.__init__, "LOAD_SUPER_ATTR_METHOD") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_contain_op(self): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def contains_op_dict(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  |                 a, b = 1, {1: 2, 2: 5} | 
					
						
							|  |  |  |                 self.assertTrue(a in b) | 
					
						
							|  |  |  |                 self.assertFalse(3 in b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         contains_op_dict() | 
					
						
							|  |  |  |         self.assert_specialized(contains_op_dict, "CONTAINS_OP_DICT") | 
					
						
							|  |  |  |         self.assert_no_opcode(contains_op_dict, "CONTAINS_OP") | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def contains_op_set(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  |                 a, b = 1, {1, 2} | 
					
						
							|  |  |  |                 self.assertTrue(a in b) | 
					
						
							|  |  |  |                 self.assertFalse(3 in b) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         contains_op_set() | 
					
						
							|  |  |  |         self.assert_specialized(contains_op_set, "CONTAINS_OP_SET") | 
					
						
							|  |  |  |         self.assert_no_opcode(contains_op_set, "CONTAINS_OP") | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-03 10:25:12 -08:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_send_with(self): | 
					
						
							|  |  |  |         def run_async(coro): | 
					
						
							|  |  |  |             while True: | 
					
						
							|  |  |  |                 try: | 
					
						
							|  |  |  |                     coro.send(None) | 
					
						
							|  |  |  |                 except StopIteration: | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         class CM: | 
					
						
							|  |  |  |             async def __aenter__(self): | 
					
						
							|  |  |  |                 return self | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             async def __aexit__(self, *exc): | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         async def send_with(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-03 10:25:12 -08:00
										 |  |  |                 async with CM(): | 
					
						
							|  |  |  |                     x = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         run_async(send_with()) | 
					
						
							|  |  |  |         # Note there are still unspecialized "SEND" opcodes in the | 
					
						
							|  |  |  |         # cleanup paths of the 'with' statement. | 
					
						
							|  |  |  |         self.assert_specialized(send_with, "SEND_GEN") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_send_yield_from(self): | 
					
						
							|  |  |  |         def g(): | 
					
						
							|  |  |  |             yield None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def send_yield_from(): | 
					
						
							|  |  |  |             yield from g() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-03 10:25:12 -08:00
										 |  |  |             list(send_yield_from()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.assert_specialized(send_yield_from, "SEND_GEN") | 
					
						
							|  |  |  |         self.assert_no_opcode(send_yield_from, "SEND") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_store_attr_slot(self): | 
					
						
							|  |  |  |         class C: | 
					
						
							|  |  |  |             __slots__ = ['x'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         def set_slot(n): | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |             c = C() | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for i in range(n): | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |                 c.x = i | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         set_slot(_testinternalcapi.SPECIALIZATION_THRESHOLD) | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assert_specialized(set_slot, "STORE_ATTR_SLOT") | 
					
						
							|  |  |  |         self.assert_no_opcode(set_slot, "STORE_ATTR") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Adding a property for 'x' should unspecialize it. | 
					
						
							|  |  |  |         C.x = property(lambda self: None, lambda self, x: None) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         set_slot(_testinternalcapi.SPECIALIZATION_COOLDOWN) | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |         self.assert_no_opcode(set_slot, "STORE_ATTR_SLOT") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_store_attr_instance_value(self): | 
					
						
							|  |  |  |         class C: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-31 02:50:54 -08:00
										 |  |  |         @reset_code | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         def set_value(n): | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |             c = C() | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for i in range(n): | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |                 c.x = i | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         set_value(_testinternalcapi.SPECIALIZATION_THRESHOLD) | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assert_specialized(set_value, "STORE_ATTR_INSTANCE_VALUE") | 
					
						
							|  |  |  |         self.assert_no_opcode(set_value, "STORE_ATTR") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Adding a property for 'x' should unspecialize it. | 
					
						
							|  |  |  |         C.x = property(lambda self: None, lambda self, x: None) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         set_value(_testinternalcapi.SPECIALIZATION_COOLDOWN) | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |         self.assert_no_opcode(set_value, "STORE_ATTR_INSTANCE_VALUE") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_store_attr_with_hint(self): | 
					
						
							|  |  |  |         class C: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         c = C() | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1): | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |             setattr(c, f"_{i}", None) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-31 02:50:54 -08:00
										 |  |  |         @reset_code | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         def set_value(n): | 
					
						
							|  |  |  |             for i in range(n): | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |                 c.x = i | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         set_value(_testinternalcapi.SPECIALIZATION_THRESHOLD) | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.assert_specialized(set_value, "STORE_ATTR_WITH_HINT") | 
					
						
							|  |  |  |         self.assert_no_opcode(set_value, "STORE_ATTR") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # Adding a property for 'x' should unspecialize it. | 
					
						
							|  |  |  |         C.x = property(lambda self: None, lambda self, x: None) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |         set_value(_testinternalcapi.SPECIALIZATION_COOLDOWN) | 
					
						
							| 
									
										
										
										
											2024-12-19 10:21:17 -08:00
										 |  |  |         self.assert_no_opcode(set_value, "STORE_ATTR_WITH_HINT") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_to_bool(self): | 
					
						
							|  |  |  |         def to_bool_bool(): | 
					
						
							|  |  |  |             true_cnt, false_cnt = 0, 0 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             elems = [e % 2 == 0 for e in range(_testinternalcapi.SPECIALIZATION_THRESHOLD)] | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  |             for e in elems: | 
					
						
							|  |  |  |                 if e: | 
					
						
							|  |  |  |                     true_cnt += 1 | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     false_cnt += 1 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             d, m = divmod(_testinternalcapi.SPECIALIZATION_THRESHOLD, 2) | 
					
						
							|  |  |  |             self.assertEqual(true_cnt, d + m) | 
					
						
							|  |  |  |             self.assertEqual(false_cnt, d) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         to_bool_bool() | 
					
						
							|  |  |  |         self.assert_specialized(to_bool_bool, "TO_BOOL_BOOL") | 
					
						
							|  |  |  |         self.assert_no_opcode(to_bool_bool, "TO_BOOL") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def to_bool_int(): | 
					
						
							|  |  |  |             count = 0 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  |                 if i: | 
					
						
							|  |  |  |                     count += 1 | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     count -= 1 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             self.assertEqual(count, _testinternalcapi.SPECIALIZATION_THRESHOLD - 2) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         to_bool_int() | 
					
						
							|  |  |  |         self.assert_specialized(to_bool_int, "TO_BOOL_INT") | 
					
						
							|  |  |  |         self.assert_no_opcode(to_bool_int, "TO_BOOL") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def to_bool_list(): | 
					
						
							|  |  |  |             count = 0 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             elems = list(range(_testinternalcapi.SPECIALIZATION_THRESHOLD)) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  |             while elems: | 
					
						
							|  |  |  |                 count += elems.pop() | 
					
						
							|  |  |  |             self.assertEqual(elems, []) | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             self.assertEqual(count, sum(range(_testinternalcapi.SPECIALIZATION_THRESHOLD))) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         to_bool_list() | 
					
						
							|  |  |  |         self.assert_specialized(to_bool_list, "TO_BOOL_LIST") | 
					
						
							|  |  |  |         self.assert_no_opcode(to_bool_list, "TO_BOOL") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def to_bool_none(): | 
					
						
							|  |  |  |             count = 0 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             elems = [None] * _testinternalcapi.SPECIALIZATION_THRESHOLD | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  |             for e in elems: | 
					
						
							|  |  |  |                 if not e: | 
					
						
							|  |  |  |                     count += 1 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             self.assertEqual(count, _testinternalcapi.SPECIALIZATION_THRESHOLD) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         to_bool_none() | 
					
						
							|  |  |  |         self.assert_specialized(to_bool_none, "TO_BOOL_NONE") | 
					
						
							|  |  |  |         self.assert_no_opcode(to_bool_none, "TO_BOOL") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def to_bool_str(): | 
					
						
							|  |  |  |             count = 0 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             elems = [""] + ["foo"] * (_testinternalcapi.SPECIALIZATION_THRESHOLD - 1) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  |             for e in elems: | 
					
						
							|  |  |  |                 if e: | 
					
						
							|  |  |  |                     count += 1 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             self.assertEqual(count, _testinternalcapi.SPECIALIZATION_THRESHOLD - 1) | 
					
						
							| 
									
										
										
										
											2024-11-22 07:52:16 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         to_bool_str() | 
					
						
							|  |  |  |         self.assert_specialized(to_bool_str, "TO_BOOL_STR") | 
					
						
							|  |  |  |         self.assert_no_opcode(to_bool_str, "TO_BOOL") | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_unpack_sequence(self): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def unpack_sequence_two_tuple(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2025-03-19 21:59:55 +01:00
										 |  |  |                 t = 1, 2 | 
					
						
							|  |  |  |                 a, b = t | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  |                 self.assertEqual(a, 1) | 
					
						
							|  |  |  |                 self.assertEqual(b, 2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         unpack_sequence_two_tuple() | 
					
						
							|  |  |  |         self.assert_specialized(unpack_sequence_two_tuple, | 
					
						
							|  |  |  |                                 "UNPACK_SEQUENCE_TWO_TUPLE") | 
					
						
							|  |  |  |         self.assert_no_opcode(unpack_sequence_two_tuple, "UNPACK_SEQUENCE") | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def unpack_sequence_tuple(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2025-03-19 21:59:55 +01:00
										 |  |  |                 a, b, c, d = 1, 2, 3, 4 | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  |                 self.assertEqual(a, 1) | 
					
						
							| 
									
										
										
										
											2025-03-19 21:59:55 +01:00
										 |  |  |                 self.assertEqual(b, 2) | 
					
						
							|  |  |  |                 self.assertEqual(c, 3) | 
					
						
							|  |  |  |                 self.assertEqual(d, 4) | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         unpack_sequence_tuple() | 
					
						
							|  |  |  |         self.assert_specialized(unpack_sequence_tuple, "UNPACK_SEQUENCE_TUPLE") | 
					
						
							|  |  |  |         self.assert_no_opcode(unpack_sequence_tuple, "UNPACK_SEQUENCE") | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         def unpack_sequence_list(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-11-22 19:00:35 +02:00
										 |  |  |                 a, b = [1, 2] | 
					
						
							|  |  |  |                 self.assertEqual(a, 1) | 
					
						
							|  |  |  |                 self.assertEqual(b, 2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |         unpack_sequence_list() | 
					
						
							|  |  |  |         self.assert_specialized(unpack_sequence_list, "UNPACK_SEQUENCE_LIST") | 
					
						
							|  |  |  |         self.assert_no_opcode(unpack_sequence_list, "UNPACK_SEQUENCE") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_binary_subscr(self): | 
					
						
							|  |  |  |         def binary_subscr_list_int(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |                 a = [1, 2, 3] | 
					
						
							|  |  |  |                 for idx, expected in enumerate(a): | 
					
						
							|  |  |  |                     self.assertEqual(a[idx], expected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_subscr_list_int() | 
					
						
							|  |  |  |         self.assert_specialized(binary_subscr_list_int, | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |                                 "BINARY_OP_SUBSCR_LIST_INT") | 
					
						
							| 
									
										
										
										
											2025-03-16 17:37:29 +01:00
										 |  |  |         self.assert_no_opcode(binary_subscr_list_int, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def binary_subscr_tuple_int(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |                 a = (1, 2, 3) | 
					
						
							|  |  |  |                 for idx, expected in enumerate(a): | 
					
						
							|  |  |  |                     self.assertEqual(a[idx], expected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_subscr_tuple_int() | 
					
						
							|  |  |  |         self.assert_specialized(binary_subscr_tuple_int, | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |                                 "BINARY_OP_SUBSCR_TUPLE_INT") | 
					
						
							| 
									
										
										
										
											2025-03-16 17:37:29 +01:00
										 |  |  |         self.assert_no_opcode(binary_subscr_tuple_int, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def binary_subscr_dict(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |                 a = {1: 2, 2: 3} | 
					
						
							|  |  |  |                 self.assertEqual(a[1], 2) | 
					
						
							|  |  |  |                 self.assertEqual(a[2], 3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_subscr_dict() | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |         self.assert_specialized(binary_subscr_dict, "BINARY_OP_SUBSCR_DICT") | 
					
						
							|  |  |  |         self.assert_no_opcode(binary_subscr_dict, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         def binary_subscr_str_int(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  |                 a = "foobar" | 
					
						
							|  |  |  |                 for idx, expected in enumerate(a): | 
					
						
							|  |  |  |                     self.assertEqual(a[idx], expected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_subscr_str_int() | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |         self.assert_specialized(binary_subscr_str_int, "BINARY_OP_SUBSCR_STR_INT") | 
					
						
							| 
									
										
										
										
											2025-03-16 17:37:29 +01:00
										 |  |  |         self.assert_no_opcode(binary_subscr_str_int, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-12-02 10:38:17 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-19 11:08:17 +09:00
										 |  |  |         def binary_subscr_getitems(): | 
					
						
							| 
									
										
										
										
											2024-12-24 02:08:34 +09:00
										 |  |  |             class C: | 
					
						
							|  |  |  |                 def __init__(self, val): | 
					
						
							|  |  |  |                     self.val = val | 
					
						
							|  |  |  |                 def __getitem__(self, item): | 
					
						
							|  |  |  |                     return self.val | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             items = [C(i) for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD)] | 
					
						
							|  |  |  |             for i in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2024-12-19 11:08:17 +09:00
										 |  |  |                 self.assertEqual(items[i][i], i) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         binary_subscr_getitems() | 
					
						
							| 
									
										
										
										
											2025-02-07 22:39:54 +00:00
										 |  |  |         self.assert_specialized(binary_subscr_getitems, "BINARY_OP_SUBSCR_GETITEM") | 
					
						
							| 
									
										
										
										
											2025-03-16 17:37:29 +01:00
										 |  |  |         self.assert_no_opcode(binary_subscr_getitems, "BINARY_OP") | 
					
						
							| 
									
										
										
										
											2024-12-19 11:08:17 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-07 06:41:01 -08:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_compare_op(self): | 
					
						
							|  |  |  |         def compare_op_int(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2025-01-07 06:41:01 -08:00
										 |  |  |                 a, b = 1, 2 | 
					
						
							|  |  |  |                 c = a == b | 
					
						
							|  |  |  |                 self.assertFalse(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         compare_op_int() | 
					
						
							|  |  |  |         self.assert_specialized(compare_op_int, "COMPARE_OP_INT") | 
					
						
							|  |  |  |         self.assert_no_opcode(compare_op_int, "COMPARE_OP") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def compare_op_float(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2025-01-07 06:41:01 -08:00
										 |  |  |                 a, b = 1.0, 2.0 | 
					
						
							|  |  |  |                 c = a == b | 
					
						
							|  |  |  |                 self.assertFalse(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         compare_op_float() | 
					
						
							|  |  |  |         self.assert_specialized(compare_op_float, "COMPARE_OP_FLOAT") | 
					
						
							|  |  |  |         self.assert_no_opcode(compare_op_float, "COMPARE_OP") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def compare_op_str(): | 
					
						
							| 
									
										
										
										
											2025-01-29 10:49:58 -08:00
										 |  |  |             for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD): | 
					
						
							| 
									
										
										
										
											2025-01-07 06:41:01 -08:00
										 |  |  |                 a, b = "spam", "ham" | 
					
						
							|  |  |  |                 c = a == b | 
					
						
							|  |  |  |                 self.assertFalse(c) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         compare_op_str() | 
					
						
							|  |  |  |         self.assert_specialized(compare_op_str, "COMPARE_OP_STR") | 
					
						
							|  |  |  |         self.assert_no_opcode(compare_op_str, "COMPARE_OP") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 05:23:47 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-12 16:21:46 +01:00
										 |  |  |     @cpython_only | 
					
						
							|  |  |  |     @requires_specialization_ft | 
					
						
							|  |  |  |     def test_for_iter(self): | 
					
						
							|  |  |  |         L = list(range(10)) | 
					
						
							|  |  |  |         def for_iter_list(): | 
					
						
							|  |  |  |             for i in L: | 
					
						
							|  |  |  |                 self.assertIn(i, L) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for_iter_list() | 
					
						
							|  |  |  |         self.assert_specialized(for_iter_list, "FOR_ITER_LIST") | 
					
						
							|  |  |  |         self.assert_no_opcode(for_iter_list, "FOR_ITER") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         t = tuple(range(10)) | 
					
						
							|  |  |  |         def for_iter_tuple(): | 
					
						
							|  |  |  |             for i in t: | 
					
						
							|  |  |  |                 self.assertIn(i, t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for_iter_tuple() | 
					
						
							|  |  |  |         self.assert_specialized(for_iter_tuple, "FOR_ITER_TUPLE") | 
					
						
							|  |  |  |         self.assert_no_opcode(for_iter_tuple, "FOR_ITER") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         r = range(10) | 
					
						
							|  |  |  |         def for_iter_range(): | 
					
						
							|  |  |  |             for i in r: | 
					
						
							|  |  |  |                 self.assertIn(i, r) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for_iter_range() | 
					
						
							|  |  |  |         self.assert_specialized(for_iter_range, "FOR_ITER_RANGE") | 
					
						
							|  |  |  |         self.assert_no_opcode(for_iter_range, "FOR_ITER") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def for_iter_generator(): | 
					
						
							|  |  |  |             for i in (i for i in range(10)): | 
					
						
							|  |  |  |                 i + 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for_iter_generator() | 
					
						
							|  |  |  |         self.assert_specialized(for_iter_generator, "FOR_ITER_GEN") | 
					
						
							|  |  |  |         self.assert_no_opcode(for_iter_generator, "FOR_ITER") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-18 10:10:22 -07:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     unittest.main() |