Files
Python3-Win9x/scripts/vc6-typeobject-add-descriptors-dict-c89.test.py

30 lines
1.6 KiB
Python

#!/usr/bin/env python3
"""Check descriptor dictionary locals and evaluation after the NULL guard."""
import re
from pathlib import Path
source = Path("cpython/Objects/typeobject.c").read_text()
failures = []
for function, local_type, local, factory in (
("type_add_members", "PyMemberDef", "memb", "PyDescr_NewMember"),
("type_add_getset", "PyGetSetDef", "gsp", "PyDescr_NewGetSet"),
):
match = re.search(r"\nstatic int\n" + function + r"\(PyTypeObject \*type\)\n\{(.*?)\n\}", source, re.S)
assert match, function + " definition missing"
body = match.group(1)
opening = rf"\s*{local_type} \*{local} = type->tp_\w+;\s*PyObject \*dict;\s*if"
if not re.match(opening, body):
failures.append(function + ": dict must be in opening C89 declarations")
continue
assert len(re.findall(r"\bPyObject\s*\*\s*dict\b", body)) == 1
assert len(re.findall(r"\bdict\s*=(?!=)", body)) == 1
guard = f"if ({local} == NULL) {{\n return 0;\n }}"
ordered = [guard, "dict = type->tp_dict;", f"for (; {local}->name != NULL; {local}++)", f"PyObject *descr = {factory}(type, {local});", "if (descr == NULL)", "return -1;", "if (PyDict_SetDefault(dict, PyDescr_NAME(descr), descr) == NULL)", "Py_DECREF(descr);", "return -1;", "Py_DECREF(descr);", "return 0;"]
cursor = 0
for token in ordered:
position = body.find(token, cursor)
assert position >= 0, f"{function}: missing/reordered operation: {token}"
cursor = position + len(token)
print(function + ": C89 dictionary declaration, NULL guard and cleanup: PASS")
assert not failures, "; ".join(failures)