42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Statically check type_new's type/res declarations and execution order."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
function = re.search(
|
|
r"\ntype_new\(PyTypeObject \*metatype, PyObject \*args, PyObject \*kwds\)\n\{(.*?)\n\}",
|
|
source, re.S,
|
|
)
|
|
assert function, "type_new definition must exist"
|
|
body = function.group(1)
|
|
assert re.match(
|
|
r"\s*PyObject \*name, \*bases, \*orig_dict;\s*"
|
|
r"type_new_ctx ctx;\s*PyObject \*type;\s*int res;\s*assert\(", body,
|
|
), "type_new: PyObject *type and int res must be in the opening declaration block"
|
|
assert len(re.findall(r"\bPyObject\s*\*type\b", body)) == 1
|
|
assert len(re.findall(r"\bint\s+res\b", body)) == 1
|
|
expected_tail = """
|
|
ctx.bases = bases;
|
|
type = NULL;
|
|
res = type_new_get_bases(&ctx, &type);
|
|
if (res < 0) {
|
|
assert(PyErr_Occurred());
|
|
return NULL;
|
|
}
|
|
if (res == 1) {
|
|
assert(type != NULL);
|
|
return type;
|
|
}
|
|
assert(ctx.base != NULL);
|
|
assert(ctx.bases != NULL);
|
|
|
|
type = type_new_impl(&ctx);
|
|
Py_DECREF(ctx.bases);
|
|
return type;
|
|
"""
|
|
assert body[body.index(" ctx.bases = bases;"):].split() == expected_tail.split(), (
|
|
"type_new: preserve assignment locations, base resolution, branches and cleanup"
|
|
)
|
|
print("type_new type/res opening declarations and execution order: PASS (static only)")
|