#!/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")