#!/usr/bin/env python3 """Check type_new_init C89 declarations and preserve all evaluation points.""" import re from pathlib import Path source = Path("cpython/Objects/typeobject.c").read_text() match = re.search( r"\nstatic PyTypeObject\*\ntype_new_init\(type_new_ctx \*ctx\)\n\{(.*?)\n\}", source, re.S, ) assert match, "type_new_init definition missing" body = match.group(1) assert re.match( r"\s*PyObject \*dict = PyDict_Copy\(ctx->orig_dict\);" r"\s*PyTypeObject \*type;\s*PyHeapTypeObject \*et;\s*if\b", body, ), "type_new_init: type and et must be in the opening declaration block (C89)" expected = '\n PyObject *dict = PyDict_Copy(ctx->orig_dict);\n PyTypeObject *type;\n PyHeapTypeObject *et;\n if (dict == NULL) {\n goto error;\n }\n\n if (type_new_get_slots(ctx, dict) < 0) {\n goto error;\n }\n assert(!PyErr_Occurred());\n\n if (type_new_slots(ctx, dict) < 0) {\n goto error;\n }\n\n type = type_new_alloc(ctx);\n if (type == NULL) {\n goto error;\n }\n\n type->tp_dict = dict;\n\n et = (PyHeapTypeObject*)type;\n et->ht_slots = ctx->slots;\n ctx->slots = NULL;\n\n return type;\n\nerror:\n Py_CLEAR(ctx->slots);\n Py_XDECREF(dict);\n return NULL;' assert body.split() == expected.split(), ( "preserve dict copy, slot checks, allocation, NULL check, dict assignment, " "heap cast, slot transfer, and error cleanup at their original evaluation points" ) print("type_new_init C89 declarations and evaluation points: PASS")