#!/usr/bin/env python3 """Guard the entry locals and evaluation order in _PyObject_FunctionStr.""" import re import sys from pathlib import Path source = Path(sys.argv[1]).read_text() found = re.search( r"\n_PyObject_FunctionStr\(PyObject \*x\)\s*\{(?P.*?)\n\}", source, re.S, ) assert found, "_PyObject_FunctionStr definition not found" body = found.group("body") for name in ("module", "result"): declarations = re.findall(r"\bPyObject\s*\*\s*" + name + r"\b", body) assert len(declarations) == 1, ( f"_PyObject_FunctionStr must declare {name} exactly once at entry; " f"found {len(declarations)} declarations" ) tokens = ( "PyObject *module;", "PyObject *result;", "int ret;", "assert(!PyErr_Occurred());", "ret = _PyObject_LookupAttr(x, &_Py_ID(__qualname__), &qualname);", "if (qualname == NULL)", "return PyObject_Str(x);", "result = NULL;", "ret = _PyObject_LookupAttr(x, &_Py_ID(__module__), &module);", "ret = PyObject_RichCompareBool(module, &_Py_ID(builtins), Py_NE);", 'result = PyUnicode_FromFormat("%S.%S()", module, qualname);', 'result = PyUnicode_FromFormat("%S()", qualname);', "Py_DECREF(qualname);", "Py_XDECREF(module);", "return result;", ) positions = [body.find(token) for token in tokens] assert all(position >= 0 for position in positions) and positions == sorted(positions), ( "_PyObject_FunctionStr must keep locals at entry and preserve evaluation/statement order" ) print("object _PyObject_FunctionStr unique C89 locals and evaluation order: PASS")