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

File tree

3 files changed

lines changed

  • Misc/NEWS.d/next/Core and Builtins

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -248,7 +248,14 @@ def __class_getitem__(cls, item):

248248

return f'{cls.__name__}[{item.__name__}]'

249249

self.assertEqual(Meta[int], 'Meta[int]')

250250
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):

252259

class Meta(type):

253260

def __getitem__(cls, item):

254261

return 'from metaclass'

Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change

@@ -143,6 +143,7 @@ PyObject *

143143

PyObject_GetItem(PyObject *o, PyObject *key)

144144

{

145145

PyMappingMethods *m;

146+

PySequenceMethods *ms;

146147
147148

if (o == NULL || key == NULL) {

148149

return null_error();

@@ -155,17 +156,19 @@ PyObject_GetItem(PyObject *o, PyObject *key)

155156

return item;

156157

}

157158
158-

if (o->ob_type->tp_as_sequence) {

159+

ms = o->ob_type->tp_as_sequence;

160+

if (ms && ms->sq_item) {

159161

if (PyIndex_Check(key)) {

160162

Py_ssize_t key_value;

161163

key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);

162164

if (key_value == -1 && PyErr_Occurred())

163165

return NULL;

164166

return PySequence_GetItem(o, key_value);

165167

}

166-

else if (o->ob_type->tp_as_sequence->sq_item)

168+

else {

167169

return type_error("sequence index must "

168170

"be integer, not '%.200s'", key);

171+

}

169172

}

170173
171174

if (PyType_Check(o)) {