|
12 | 12 | _testcapi = import_helper.import_module("_testcapi")
|
13 | 13 | type_get_version = _testcapi.type_get_version
|
14 | 14 | type_assign_specific_version_unsafe = _testcapi.type_assign_specific_version_unsafe
|
15 |
| -type_assign_version = _testcapi.type_assign_version |
16 | 15 | type_modified = _testcapi.type_modified
|
17 | 16 |
|
18 | 17 |
|
| 18 | +def type_assign_version(type_): |
| 19 | + try: |
| 20 | + type_.x |
| 21 | + except AttributeError: |
| 22 | + pass |
| 23 | + |
| 24 | + |
19 | 25 | @support.cpython_only
|
20 | 26 | @unittest.skipIf(_clear_type_cache is None, "requires sys._clear_type_cache")
|
21 | 27 | class TypeCacheTests(unittest.TestCase):
|
@@ -47,19 +53,6 @@ def test_tp_version_tag_unique(self):
|
47 | 53 | self.assertEqual(len(set(all_version_tags)), 30,
|
48 | 54 | msg=f"{all_version_tags} contains non-unique versions")
|
49 | 55 |
|
50 |
| - def test_type_assign_version(self): |
51 |
| - class C: |
52 |
| - x = 5 |
53 |
| - |
54 |
| - self.assertEqual(type_assign_version(C), 1) |
55 |
| - c_ver = type_get_version(C) |
56 |
| - |
57 |
| - C.x = 6 |
58 |
| - self.assertEqual(type_get_version(C), 0) |
59 |
| - self.assertEqual(type_assign_version(C), 1) |
60 |
| - self.assertNotEqual(type_get_version(C), 0) |
61 |
| - self.assertNotEqual(type_get_version(C), c_ver) |
62 |
| - |
63 | 56 | def test_type_assign_specific_version(self):
|
64 | 57 | """meta-test for type_assign_specific_version_unsafe"""
|
65 | 58 | class C:
|
@@ -108,134 +101,103 @@ def _check_specialization(self, func, arg, opname, *, should_specialize):
|
108 | 101 | else:
|
109 | 102 | self.assertIn(opname, self._all_opnames(func))
|
110 | 103 |
|
111 |
| - def test_class_load_attr_specialization_user_type(self): |
| 104 | + def test_load_method_specialization_user_type(self): |
112 | 105 | class A:
|
113 | 106 | def foo(self):
|
114 | 107 | pass
|
115 | 108 |
|
116 | 109 | self._assign_valid_version_or_skip(A)
|
117 | 110 |
|
118 |
| - def load_foo_1(type_): |
119 |
| - type_.foo |
| 111 | + def load_foo_1(instance): |
| 112 | + instance.foo() |
120 | 113 |
|
121 |
| - self._check_specialization(load_foo_1, A, "LOAD_ATTR", should_specialize=True) |
| 114 | + self._check_specialization( |
| 115 | + load_foo_1, A(), "LOAD_METHOD_ADAPTIVE", should_specialize=True |
| 116 | + ) |
122 | 117 | del load_foo_1
|
123 | 118 |
|
124 | 119 | self._assign_and_check_version_0(A)
|
125 | 120 |
|
126 |
| - def load_foo_2(type_): |
127 |
| - return type_.foo |
128 |
| - |
129 |
| - self._check_specialization(load_foo_2, A, "LOAD_ATTR", should_specialize=False) |
130 |
| - |
131 |
| - def test_class_load_attr_specialization_static_type(self): |
132 |
| - self._assign_valid_version_or_skip(str) |
133 |
| - self._assign_valid_version_or_skip(bytes) |
134 |
| - |
135 |
| - def get_capitalize_1(type_): |
136 |
| - return type_.capitalize |
137 |
| - |
138 |
| - self._check_specialization(get_capitalize_1, str, "LOAD_ATTR", should_specialize=True) |
139 |
| - self.assertEqual(get_capitalize_1(str)('hello'), 'Hello') |
140 |
| - self.assertEqual(get_capitalize_1(bytes)(b'hello'), b'Hello') |
141 |
| - del get_capitalize_1 |
142 |
| - |
143 |
| - # Permanently overflow the static type version counter, and force str and bytes |
144 |
| - # to have tp_version_tag == 0 |
145 |
| - for _ in range(2**16): |
146 |
| - type_modified(str) |
147 |
| - type_assign_version(str) |
148 |
| - type_modified(bytes) |
149 |
| - type_assign_version(bytes) |
150 |
| - |
151 |
| - self.assertEqual(type_get_version(str), 0) |
152 |
| - self.assertEqual(type_get_version(bytes), 0) |
153 |
| - |
154 |
| - def get_capitalize_2(type_): |
155 |
| - return type_.capitalize |
| 121 | + def load_foo_2(instance): |
| 122 | + instance.foo() |
156 | 123 |
|
157 |
| - self._check_specialization(get_capitalize_2, str, "LOAD_ATTR", should_specialize=False) |
158 |
| - self.assertEqual(get_capitalize_2(str)('hello'), 'Hello') |
159 |
| - self.assertEqual(get_capitalize_2(bytes)(b'hello'), b'Hello') |
160 |
| - |
161 |
| - def test_property_load_attr_specialization_user_type(self): |
162 |
| - class G: |
163 |
| - @property |
164 |
| - def x(self): |
165 |
| - return 9 |
166 |
| - |
167 |
| - self._assign_valid_version_or_skip(G) |
168 |
| - |
169 |
| - def load_x_1(instance): |
170 |
| - instance.x |
171 |
| - |
172 |
| - self._check_specialization(load_x_1, G(), "LOAD_ATTR", should_specialize=True) |
173 |
| - del load_x_1 |
174 |
| - |
175 |
| - self._assign_and_check_version_0(G) |
176 |
| - |
177 |
| - def load_x_2(instance): |
178 |
| - instance.x |
179 |
| - |
180 |
| - self._check_specialization(load_x_2, G(), "LOAD_ATTR", should_specialize=False) |
| 124 | + self._check_specialization( |
| 125 | + load_foo_2, A(), "LOAD_METHOD_ADAPTIVE", should_specialize=False |
| 126 | + ) |
181 | 127 |
|
182 | 128 | def test_store_attr_specialization_user_type(self):
|
183 | 129 | class B:
|
184 | 130 | __slots__ = ("bar",)
|
185 | 131 |
|
186 | 132 | self._assign_valid_version_or_skip(B)
|
187 | 133 |
|
188 |
| - def store_bar_1(type_): |
189 |
| - type_.bar = 10 |
| 134 | + def store_bar_1(instance): |
| 135 | + instance.bar = 10 |
190 | 136 |
|
191 |
| - self._check_specialization(store_bar_1, B(), "STORE_ATTR", should_specialize=True) |
| 137 | + self._check_specialization( |
| 138 | + store_bar_1, B(), "STORE_ATTR_ADAPTIVE", should_specialize=True |
| 139 | + ) |
192 | 140 | del store_bar_1
|
193 | 141 |
|
194 | 142 | self._assign_and_check_version_0(B)
|
195 | 143 |
|
196 |
| - def store_bar_2(type_): |
197 |
| - type_.bar = 10 |
| 144 | + def store_bar_2(instance): |
| 145 | + instance.bar = 10 |
198 | 146 |
|
199 |
| - self._check_specialization(store_bar_2, B(), "STORE_ATTR", should_specialize=False) |
| 147 | + self._check_specialization( |
| 148 | + store_bar_2, B(), "STORE_ATTR_ADAPTIVE", should_specialize=False |
| 149 | + ) |
200 | 150 |
|
201 |
| - def test_class_call_specialization_user_type(self): |
202 |
| - class F: |
| 151 | + def test_load_attr_specialization_user_type(self): |
| 152 | + class C: |
| 153 | + __slots__ = ("biz",) |
203 | 154 | def __init__(self):
|
204 |
| - pass |
| 155 | + self.biz = 8 |
205 | 156 |
|
206 |
| - self._assign_valid_version_or_skip(F) |
| 157 | + self._assign_valid_version_or_skip(C) |
207 | 158 |
|
208 |
| - def call_class_1(type_): |
209 |
| - type_() |
| 159 | + def load_biz_1(type_): |
| 160 | + type_.biz |
210 | 161 |
|
211 |
| - self._check_specialization(call_class_1, F, "CALL", should_specialize=True) |
212 |
| - del call_class_1 |
| 162 | + self._check_specialization( |
| 163 | + load_biz_1, C(), "LOAD_ATTR_ADAPTIVE", should_specialize=True |
| 164 | + ) |
| 165 | + del load_biz_1 |
213 | 166 |
|
214 |
| - self._assign_and_check_version_0(F) |
| 167 | + self._assign_and_check_version_0(C) |
215 | 168 |
|
216 |
| - def call_class_2(type_): |
217 |
| - type_() |
| 169 | + def load_biz_2(type_): |
| 170 | + type_.biz |
218 | 171 |
|
219 |
| - self._check_specialization(call_class_2, F, "CALL", should_specialize=False) |
| 172 | + self._check_specialization( |
| 173 | + load_biz_2, C(), "LOAD_ATTR_ADAPTIVE", should_specialize=False |
| 174 | + ) |
220 | 175 |
|
221 |
| - def test_to_bool_specialization_user_type(self): |
222 |
| - class H: |
223 |
| - pass |
| 176 | + def test_binary_subscript_specialization_user_type(self): |
| 177 | + class D: |
| 178 | + def __getitem__(self, _): |
| 179 | + return 1 |
| 180 | + |
| 181 | + self._assign_valid_version_or_skip(D) |
| 182 | + |
| 183 | + def subscript_1(instance): |
| 184 | + instance[6] |
224 | 185 |
|
225 |
| - self._assign_valid_version_or_skip(H) |
| 186 | + self._check_specialization( |
| 187 | + subscript_1, D(), "BINARY_SUBSCR_ADAPTIVE", should_specialize=True |
| 188 | + ) |
| 189 | + del subscript_1 |
226 | 190 |
|
227 |
| - def to_bool_1(instance): |
228 |
| - not instance |
| 191 | + self._assign_and_check_version_0(D) |
229 | 192 |
|
230 |
| - self._check_specialization(to_bool_1, H(), "TO_BOOL", should_specialize=True) |
231 |
| - del to_bool_1 |
| 193 | + def subscript_2(instance): |
| 194 | + instance[6] |
232 | 195 |
|
233 |
| - self._assign_and_check_version_0(H) |
| 196 | + self._check_specialization( |
| 197 | + subscript_2, D(), "BINARY_SUBSCR_ADAPTIVE", should_specialize=False |
| 198 | + ) |
234 | 199 |
|
235 |
| - def to_bool_2(instance): |
236 |
| - not instance |
237 | 200 |
|
238 |
| - self._check_specialization(to_bool_2, H(), "TO_BOOL", should_specialize=False) |
239 | 201 |
|
240 | 202 | if __name__ == "__main__":
|
241 | 203 | unittest.main()
|
0 commit comments