bpo-35992: Use PySequence_GetItem only if sq_item is not NULL (GH-11857) · python/cpython@ac28147 (original) (raw)

File tree

3 files changed

lines changed

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -248,7 +248,14 @@ def __class_getitem__(cls, item):
248 248 return f'{cls.__name__}[{item.__name__}]'
249 249 self.assertEqual(Meta[int], 'Meta[int]')
250 250
251 -def test_class_getitem_metaclass_2(self):
251 +def test_class_getitem_with_metaclass(self):
252 +class Meta(type): pass
253 +class C(metaclass=Meta):
254 +def __class_getitem__(cls, item):
255 +return f'{cls.__name__}[{item.__name__}]'
256 +self.assertEqual(C[int], 'C[int]')
257 +
258 +def test_class_getitem_metaclass_first(self):
252 259 class Meta(type):
253 260 def __getitem__(cls, item):
254 261 return 'from metaclass'
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 +Fix ``__class_getitem__()`` not being called on a class with a custom
2 +non-subscriptable metaclass.
Original file line number Diff line number Diff line change
@@ -143,6 +143,7 @@ PyObject *
143 143 PyObject_GetItem(PyObject *o, PyObject *key)
144 144 {
145 145 PyMappingMethods *m;
146 +PySequenceMethods *ms;
146 147
147 148 if (o == NULL |
148 149 return null_error();
@@ -155,17 +156,19 @@ PyObject_GetItem(PyObject *o, PyObject *key)
155 156 return item;
156 157 }
157 158
158 -if (o->ob_type->tp_as_sequence) {
159 +ms = o->ob_type->tp_as_sequence;
160 +if (ms && ms->sq_item) {
159 161 if (PyIndex_Check(key)) {
160 162 Py_ssize_t key_value;
161 163 key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
162 164 if (key_value == -1 && PyErr_Occurred())
163 165 return NULL;
164 166 return PySequence_GetItem(o, key_value);
165 167 }
166 -else if (o->ob_type->tp_as_sequence->sq_item)
168 +else {
167 169 return type_error("sequence index must "
168 170 "be integer, not '%.200s'", key);
171 + }
169 172 }
170 173
171 174 if (PyType_Check(o)) {