Files
Python3-Win9x/scripts/vc6-typeobject-mro-hierarchy-loop-c89.test.py
T

48 lines
1.7 KiB
Python

#!/usr/bin/env python3
"""Check mro_hierarchy's n/i declarations and guarded subclass loop timing."""
import re
from pathlib import Path
source = Path("cpython/Objects/typeobject.c").read_text()
match = re.search(
r"\nstatic int\nmro_hierarchy\(PyTypeObject \*type, PyObject \*temp\)\n\{(.*?)\n\}",
source,
re.S,
)
assert match, "mro_hierarchy definition missing"
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
assert re.match(
r"\s*PyObject \*old_mro;\s*PyObject \*new_mro;\s*PyObject \*tuple;"
r"\s*Py_ssize_t n;\s*Py_ssize_t i;\s*int res = mro_internal\(", body
), "mro_hierarchy: n and i must be uninitialized opening function declarations"
for name in ("n", "i"):
assert len(re.findall(rf"\bPy_ssize_t\s+{name}\b", body)) == 1, (
f"mro_hierarchy: declare {name} exactly once"
)
assert len(re.findall(rf"\b{name}\s*=(?!=)", body)) == 1, (
f"mro_hierarchy: initialize {name} exactly once at its original point"
)
expected = """
if (type->tp_subclasses != NULL) {
PyObject *subclasses = _PyType_GetSubclasses(type);
if (subclasses == NULL) {
return -1;
}
n = PyList_GET_SIZE(subclasses);
for (i = 0; i < n; i++) {
PyTypeObject *subclass = _PyType_CAST(PyList_GET_ITEM(subclasses, i));
res = mro_hierarchy(subclass, temp);
if (res < 0) {
break;
}
}
Py_DECREF(subclasses);
}
return res;
"""
tail = body[body.index("if (type->tp_subclasses != NULL)"):]
assert tail.split() == expected.split(), (
"mro_hierarchy: preserve NULL guard, size read, loop, cleanup, and return"
)
print("mro_hierarchy n/i C89 declarations and guarded subclass loop timing: PASS")