[3.7] bpo-28866: No type cache for types with specialized mro, invali… · python/cpython@bfd0b77 (original) (raw)

`@@ -77,6 +77,9 @@ slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds);

`

77

77

`static void

`

78

78

`clear_slotdefs(void);

`

79

79

``

``

80

`+

static PyObject *

`

``

81

`+

lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound);

`

``

82

+

80

83

`/*

`

81

84

` * finds the beginning of the docstring's introspection signature.

`

82

85

` * if present, returns a pointer pointing to the first '('.

`

`@@ -281,17 +284,35 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {

`

281

284

``

282

285

` Unset HAVE_VERSION_TAG and VALID_VERSION_TAG if the type

`

283

286

` has a custom MRO that includes a type which is not officially

`

284

``

`-

super type.

`

``

287

`+

super type, or if the type implements its own mro() method.

`

285

288

``

286

289

` Called from mro_internal, which will subsequently be called on

`

287

290

` each subclass when their mro is recursively updated.

`

288

291

` */

`

289

292

`Py_ssize_t i, n;

`

290

``

`-

int clear = 0;

`

``

293

`+

int custom = (Py_TYPE(type) != &PyType_Type);

`

``

294

`+

int unbound;

`

``

295

`+

PyObject *mro_meth = NULL;

`

``

296

`+

PyObject *type_mro_meth = NULL;

`

291

297

``

292

298

`if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))

`

293

299

`return;

`

294

300

``

``

301

`+

if (custom) {

`

``

302

`+

_Py_IDENTIFIER(mro);

`

``

303

`+

mro_meth = lookup_maybe_method(

`

``

304

`+

(PyObject *)type, &PyId_mro, &unbound);

`

``

305

`+

if (mro_meth == NULL)

`

``

306

`+

goto clear;

`

``

307

`+

type_mro_meth = lookup_maybe_method(

`

``

308

`+

(PyObject *)&PyType_Type, &PyId_mro, &unbound);

`

``

309

`+

if (type_mro_meth == NULL)

`

``

310

`+

goto clear;

`

``

311

`+

if (mro_meth != type_mro_meth)

`

``

312

`+

goto clear;

`

``

313

`+

Py_XDECREF(mro_meth);

`

``

314

`+

Py_XDECREF(type_mro_meth);

`

``

315

`+

}

`

295

316

`n = PyTuple_GET_SIZE(bases);

`

296

317

`for (i = 0; i < n; i++) {

`

297

318

`PyObject *b = PyTuple_GET_ITEM(bases, i);

`

`@@ -302,14 +323,15 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {

`

302

323

``

303

324

`if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||

`

304

325

` !PyType_IsSubtype(type, cls)) {

`

305

``

`-

clear = 1;

`

306

``

`-

break;

`

``

326

`+

goto clear;

`

307

327

` }

`

308

328

` }

`

309

``

-

310

``

`-

if (clear)

`

311

``

`-

type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|

`

312

``

`-

Py_TPFLAGS_VALID_VERSION_TAG);

`

``

329

`+

return;

`

``

330

`+

clear:

`

``

331

`+

Py_XDECREF(mro_meth);

`

``

332

`+

Py_XDECREF(type_mro_meth);

`

``

333

`+

type->tp_flags &= ~(Py_TPFLAGS_HAVE_VERSION_TAG|

`

``

334

`+

Py_TPFLAGS_VALID_VERSION_TAG);

`

313

335

`}

`

314

336

``

315

337

`static int

`