#!/usr/bin/env python3 """Check type_new_alloc's C89 heap-type declaration and cast timing.""" import re from pathlib import Path source = Path("cpython/Objects/typeobject.c").read_text() match = re.search( r"\nstatic PyTypeObject\*\ntype_new_alloc\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", source, re.S, ) assert match, "type_new_alloc definition missing" body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) assert re.match( r"\s*PyTypeObject \*metatype = ctx->metatype;" r"\s*PyTypeObject \*type;\s*PyHeapTypeObject \*et;\s*type\s*=", body, ), "type_new_alloc: et must be in the opening declaration block (C89)" assert len(re.findall(r"\bPyHeapTypeObject\s*\*\s*et\b", body)) == 1, ( "declare et exactly once" ) assert len(re.findall(r"\bet\s*=(?!=)", body)) == 1, ( "assign et exactly once" ) expected = """ PyTypeObject *metatype = ctx->metatype; PyTypeObject *type; PyHeapTypeObject *et; type = (PyTypeObject *)metatype->tp_alloc(metatype, ctx->nslot); if (type == NULL) { return NULL; } et = (PyHeapTypeObject *)type; """ prefix = body.split("type->tp_flags =", 1)[0] assert prefix.split() == expected.split(), ( "type_new_alloc: preserve allocation, NULL check, and heap-type cast " "before flag initialization in their original order" ) print("type_new_alloc heap-type C89 declaration and cast timing: PASS")