46 lines
1.6 KiB
Python
46 lines
1.6 KiB
Python
#!/usr/bin/env python3
|
|
"""Check the empty-bases declaration and preserve tuple allocation timing."""
|
|
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"if \(nbases == 0\) \{\s*PyObject \*new_bases;\s*ctx->base =",
|
|
body,
|
|
), "type_new_get_bases: new_bases must open the empty-bases block (C89)"
|
|
assert len(re.findall(r"\bPyObject\s*\*\s*new_bases\b", body)) == 1, (
|
|
"declare new_bases exactly once"
|
|
)
|
|
assert len(re.findall(r"\bnew_bases\s*=(?!=)", body)) == 1, (
|
|
"assign new_bases exactly once"
|
|
)
|
|
prefix = body.split("\n for (", 1)[0]
|
|
# Permit the separately tested C89 loop-index and winner declarations.
|
|
prefix = re.sub(
|
|
r"\n (?:Py_ssize_t i|PyTypeObject \*(?:winner|base));", "", prefix
|
|
)
|
|
expected = """
|
|
Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases);
|
|
if (nbases == 0) {
|
|
PyObject *new_bases;
|
|
ctx->base = &PyBaseObject_Type;
|
|
new_bases = PyTuple_Pack(1, ctx->base);
|
|
if (new_bases == NULL) {
|
|
return -1;
|
|
}
|
|
ctx->bases = new_bases;
|
|
return 0;
|
|
}
|
|
"""
|
|
assert prefix.split() == expected.split(), (
|
|
"preserve empty-bases guard, base assignment, tuple allocation, NULL check, "
|
|
"bases transfer, and early returns at their original evaluation points"
|
|
)
|
|
print("type_new_get_bases new_bases C89 declaration and allocation timing: PASS")
|