Files
Python3-Win9x/scripts/vc6-typeobject-type-new-get-bases-mro-entries-c89.test.py

47 lines
1.7 KiB
Python

#!/usr/bin/env python3
"""Check the mro_entries declaration and preserve base lookup ordering."""
import re
from pathlib import Path
source = Path("cpython/Objects/typeobject.c").read_text()
match = re.search(
r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}",
source, re.S,
)
assert match, "type_new_get_bases definition missing"
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
assert re.search(
r"for \(i = 0; i < nbases; i\+\+\) \{\s*"
r"PyObject \*base = PyTuple_GET_ITEM\(ctx->bases, i\);\s*"
r"PyObject \*mro_entries;\s*if \(PyType_Check\(base\)\)",
body,
), "type_new_get_bases: mro_entries must precede loop statements (C89)"
assert len(re.findall(r"\bPyObject\s*\*\s*mro_entries\b", body)) == 1, (
"declare mro_entries exactly once"
)
loop = body[body.index(" for ("):body.index(" winner = _PyType_CalculateMetaclass(")]
expected = """
for (i = 0; i < nbases; i++) {
PyObject *base = PyTuple_GET_ITEM(ctx->bases, i);
PyObject *mro_entries;
if (PyType_Check(base)) {
continue;
}
if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__),
&mro_entries) < 0) {
return -1;
}
if (mro_entries != NULL) {
PyErr_SetString(PyExc_TypeError,
"type() doesn't support MRO entry resolution; "
"use types.new_class()");
Py_DECREF(mro_entries);
return -1;
}
}
"""
assert loop.split() == expected.split(), (
"preserve base lookup, type skip, attribute lookup, error handling, and decref order"
)
print("type_new_get_bases mro_entries C89 declaration and lookup ordering: PASS")