47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Check mro_check's C89 base declaration and validation/cast order."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
match = re.search(
|
|
r"\nstatic int\nmro_check\(PyTypeObject \*type, PyObject \*mro\)\n\{(.*?)\n\}",
|
|
source,
|
|
re.S,
|
|
)
|
|
assert match, "mro_check definition missing"
|
|
body = match.group(1)
|
|
loop = body[body.index(" for (i = 0; i < n; i++) {"):]
|
|
opening = loop.split("if (!PyType_Check(obj))", 1)[0]
|
|
assert re.search(r"\bPyTypeObject \*base;", opening), (
|
|
"mro_check: PyTypeObject *base; must precede loop statements (C89)"
|
|
)
|
|
expected = """
|
|
for (i = 0; i < n; i++) {
|
|
PyObject *obj = PyTuple_GET_ITEM(mro, i);
|
|
PyTypeObject *base;
|
|
if (!PyType_Check(obj)) {
|
|
PyErr_Format(
|
|
PyExc_TypeError,
|
|
"mro() returned a non-class ('%.500s')",
|
|
Py_TYPE(obj)->tp_name);
|
|
return -1;
|
|
}
|
|
base = (PyTypeObject*)obj;
|
|
|
|
if (!PyType_IsSubtype(solid, solid_base(base))) {
|
|
PyErr_Format(
|
|
PyExc_TypeError,
|
|
"mro() returned base with unsuitable layout ('%.500s')",
|
|
base->tp_name);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
"""
|
|
assert loop.split() == expected.split(), (
|
|
"preserve item lookup, non-class rejection before cast, layout validation, and returns"
|
|
)
|
|
print("mro_check C89 base declaration and unchanged validation/cast order: PASS")
|