Files
Python3-Win9x/scripts/vc6-typeobject-subtype-traverse-err-c89.test.py
T

49 lines
1.8 KiB
Python

#!/usr/bin/env python3
"""Keep subtype_traverse's managed-dict err C89-safe without moving evaluation."""
import re
import sys
from pathlib import Path
source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/typeobject.c").read_text()
match = re.search(
r"\nstatic int\nsubtype_traverse\(PyObject \*self, visitproc visit, void \*arg\)\n\{(.*?)\n\}",
source,
re.S,
)
assert match, "subtype_traverse definition missing"
body = match.group(1)
assert re.match(
r"\s*PyTypeObject \*type, \*base;\s*traverseproc basetraverse;\s*int err;",
body,
), "subtype_traverse: managed-dict err must be declared at function entry (C89)"
assert len(re.findall(r"\bint\s+err\b", body)) == 2, (
"subtype_traverse: retain the separate slot-local err and one function-local err"
)
expected = """
if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT) {
assert(type->tp_dictoffset);
err = _PyObject_VisitInstanceAttributes(self, visit, arg);
if (err) {
return err;
}
}
"""
managed_dict = body[body.index(" if (type->tp_flags & Py_TPFLAGS_MANAGED_DICT)"):body.index(" if (type->tp_dictoffset != base->tp_dictoffset)")]
assert managed_dict.split() == expected.split(), (
"subtype_traverse: preserve guarded evaluation after assertion and error propagation"
)
assert body.count("_PyObject_VisitInstanceAttributes(") == 1, (
"subtype_traverse: visit instance attributes exactly once"
)
slots = """
if (Py_SIZE(base)) {
int err = traverse_slots(base, self, visit, arg);
if (err)
return err;
}
"""
assert " ".join(slots.split()) in " ".join(body.split()), (
"subtype_traverse: preserve the slot-local err declaration and control flow"
)
print("subtype_traverse managed-dict err C89 declaration and unchanged evaluation/control flow: PASS")