#!/usr/bin/env python3 """Keep _PyType_GetSubclasses's subclasses declaration C89-safe.""" import re from pathlib import Path source = Path("cpython/Objects/typeobject.c").read_text() match = re.search( r"\nPyObject\*\n_PyType_GetSubclasses\(PyTypeObject \*self\)\n\{(.*?)\n\}", source, re.S, ) assert match, "_PyType_GetSubclasses definition missing" body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S) assert re.match(r"\s*PyObject \*subclasses;", body), ( "_PyType_GetSubclasses: subclasses must be declared at function entry (C89)" ) assert len(re.findall(r"\bPyObject\s*\*\s*subclasses\b", body)) == 1, ( "_PyType_GetSubclasses: declare subclasses exactly once" ) assert re.match( r"\s*PyObject \*subclasses;\s*" r"(?:Py_ssize_t i;\s*)?" r"PyObject \*list = PyList_New\(0\);\s*" r"PyObject \*ref;\s*" r"PyObject \*obj;\s*" r"if \(list == NULL\) \{\s*return NULL;\s*\}\s*" r"subclasses = self->tp_subclasses;\s*" r"if \(subclasses == NULL\) \{\s*return list;\s*\}\s*" r"assert\(PyDict_CheckExact\(subclasses\)\);", body, ), "_PyType_GetSubclasses: preserve allocation, guard, and tp_subclasses read timing" assert body.count("self->tp_subclasses") == 1, ( "_PyType_GetSubclasses: preserve the single tp_subclasses read" ) print("_PyType_GetSubclasses subclasses C89 declaration and read timing: PASS")