#!/usr/bin/env python3 """Check only mro_implementation's single-base fast-path loop index.""" import re from pathlib import Path source = Path("cpython/Objects/typeobject.c").read_text() match = re.search( r"\nstatic PyObject \*\nmro_implementation\(PyTypeObject \*type\)\n\{(.*?)\n\}", source, re.S, ) assert match, "mro_implementation definition missing" body = re.sub(r"/\*.*?\*/", "", match.group(1), flags=re.S) assert re.match( r"\s*PyObject \*bases;\s*Py_ssize_t n;\s*Py_ssize_t i;" r"\s*PyObject \*\*to_merge;\s*PyObject \*result;\s*if\b", body, ), ( "mro_implementation: reuse i from the opening declaration block" ) fast_path = body.split("if (n == 1) {", 1)[1].split("return result;", 1)[0] assert not re.search(r"\bPy_ssize_t\s+i\b", fast_path), ( "mro_implementation: fast-path loop must reuse function-scope i for C89" ) expected = """ PyTypeObject *base = _PyType_CAST(PyTuple_GET_ITEM(bases, 0)); Py_ssize_t k = PyTuple_GET_SIZE(base->tp_mro); PyObject *result = PyTuple_New(k + 1); if (result == NULL) { return NULL; } Py_INCREF(type); PyTuple_SET_ITEM(result, 0, (PyObject *) type); for (i = 0; i < k; i++) { PyObject *cls = PyTuple_GET_ITEM(base->tp_mro, i); Py_INCREF(cls); PyTuple_SET_ITEM(result, i + 1, cls); } """ assert fast_path.split() == expected.split(), ( "mro_implementation: preserve fast-path initialization timing, loop bounds, " "increment, allocation, reference counts, and tuple writes" ) print("mro_implementation fast-path loop index C89 declaration and unchanged semantics: PASS")