Files
Python3-Win9x/scripts/vc6-typeobject-from-module-and-spec-memb-c89.test.py
T

56 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Keep the type-spec member loop C89-safe without moving its initialization."""
import re
from pathlib import Path
source = Path("cpython/Objects/typeobject.c").read_text()
match = re.search(
r"\nPyObject \*\nPyType_FromModuleAndSpec\(PyObject \*module, PyType_Spec \*spec, PyObject \*bases\)\n"
r"\{(.*?)\n\}",
source,
re.S,
)
assert match, "PyType_FromModuleAndSpec definition missing"
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
assert re.search(
r"if \(slot->slot == Py_tp_members\)\s*\{"
r"\s*const PyMemberDef \*memb;\s*nmembers = 0;"
r"\s*for \(memb = slot->pfunc; memb->name != NULL; memb\+\+\)\s*\{",
body,
), "memb must be declared at block start (C89), with initialization still in the loop header"
assert len(re.findall(r"\bconst PyMemberDef\s*\*memb\b", body)) == 1, (
"declare memb exactly once"
)
scan = body[body.index(" nmembers = weaklistoffset"):body.index(" res = (PyHeapTypeObject*)")]
expected = """
nmembers = weaklistoffset = dictoffset = vectorcalloffset = 0;
for (slot = spec->slots; slot->slot; slot++) {
if (slot->slot == Py_tp_members) {
const PyMemberDef *memb;
nmembers = 0;
for (memb = slot->pfunc; memb->name != NULL; memb++) {
nmembers++;
if (strcmp(memb->name, "__weaklistoffset__") == 0) {
assert(memb->type == T_PYSSIZET);
assert(memb->flags == READONLY);
weaklistoffset = memb->offset;
}
if (strcmp(memb->name, "__dictoffset__") == 0) {
assert(memb->type == T_PYSSIZET);
assert(memb->flags == READONLY);
dictoffset = memb->offset;
}
if (strcmp(memb->name, "__vectorcalloffset__") == 0) {
assert(memb->type == T_PYSSIZET);
assert(memb->flags == READONLY);
vectorcalloffset = memb->offset;
}
}
}
}
"""
assert scan.split() == expected.split(), (
"preserve member scan guards, evaluation order, bounds, increments, and offset handling"
)
print("PyType_FromModuleAndSpec memb C89 declaration and same-point initialization: PASS")