43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Check type_new argument declarations without crossing the ctx frontier."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
match = re.search(
|
|
r"\nstatic PyObject \*\ntype_new\(PyTypeObject \*metatype, "
|
|
r"PyObject \*args, PyObject \*kwds\)\n\{(.*?)\n\}",
|
|
source, re.S,
|
|
)
|
|
assert match, "type_new definition missing"
|
|
body = match.group(1)
|
|
assert re.match(r"\s*PyObject \*name, \*bases, \*orig_dict;\s*type_new_ctx ctx;\s*"
|
|
r"PyObject \*type;\s*int res;\s*assert\(", body), (
|
|
"type_new: name, bases, orig_dict must precede statements (C89)"
|
|
)
|
|
expected_prefix = '''
|
|
PyObject *name, *bases, *orig_dict;
|
|
type_new_ctx ctx;
|
|
PyObject *type;
|
|
int res;
|
|
|
|
assert(args != NULL && PyTuple_Check(args));
|
|
assert(kwds == NULL || PyDict_Check(kwds));
|
|
|
|
/* Parse arguments: (name, bases, dict) */
|
|
if (!PyArg_ParseTuple(args, "UO!O!:type.__new__",
|
|
&name,
|
|
&PyTuple_Type, &bases,
|
|
&PyDict_Type, &orig_dict))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
'''
|
|
prefix, separator, _ = body.partition("memset(&ctx, 0, sizeof(ctx));")
|
|
assert separator, "post-parse context zero-initialization frontier must remain"
|
|
assert prefix.split() == expected_prefix.split(), (
|
|
"preserve assertion order, argument parsing, and failure return before ctx"
|
|
)
|
|
print("type_new argument declarations and evaluation order: PASS")
|