#!/usr/bin/env python3 """Check type_repr's C89 locals and preserve assignment/evaluation/control flow.""" import re from pathlib import Path source = Path("cpython/Objects/typeobject.c").read_text() match = re.search( r"\nstatic PyObject \*\ntype_repr\(PyTypeObject \*type\)\n\{(.*?)\n\}", source, re.S, ) assert match, "type_repr definition missing" body = match.group(1) assert re.match(r"\s*PyObject \*mod, \*name, \*rtn;\s*if\b", body), ( "type_repr: PyObject *mod, *name, *rtn; must be in the opening declaration block" ) assert body.count("PyObject *mod, *name, *rtn;") == 1, ( "type_repr: declare mod, name, and rtn exactly once" ) expected = """ PyObject *mod, *name, *rtn; if (type->tp_name == NULL) { // type_repr() called before the type is fully initialized // by PyType_Ready(). return PyUnicode_FromFormat("", type); } mod = type_module(type, NULL); if (mod == NULL) PyErr_Clear(); else if (!PyUnicode_Check(mod)) { Py_DECREF(mod); mod = NULL; } name = type_qualname(type, NULL); if (name == NULL) { Py_XDECREF(mod); return NULL; } if (mod != NULL && !_PyUnicode_Equal(mod, &_Py_ID(builtins))) rtn = PyUnicode_FromFormat("", mod, name); else rtn = PyUnicode_FromFormat("", type->tp_name); Py_XDECREF(mod); Py_DECREF(name); return rtn; """ assert body.split() == expected.split(), ( "type_repr: preserve all assignments, evaluation order, and control flow" ) print("type_repr locals C89 declaration and unchanged assignment/evaluation/control flow: PASS")