Files
Python3-Win9x/scripts/vc6-typeobject-object-set-class-newto-c89.test.py
T

43 lines
1.6 KiB
Python

#!/usr/bin/env python3
"""Check object_set_class's C89 newto declaration and evaluation timing."""
import re
from pathlib import Path
source = Path("cpython/Objects/typeobject.c").read_text()
match = re.search(
r"\nstatic int\nobject_set_class\(PyObject \*self, PyObject \*value, "
r"void \*closure\)\n\{(.*?)\n\}", source, re.S,
)
assert match, "object_set_class definition missing"
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
assert re.match(
r"\s*PyTypeObject \*oldto = Py_TYPE\(self\);\s*PyTypeObject \*newto;\s*if",
body,
), "object_set_class: newto must be in the opening declaration block (C89)"
assert len(re.findall(r"\bPyTypeObject\s*\*\s*newto\b", body)) == 1, "declare newto exactly once"
assert len(re.findall(r"\bnewto\s*=(?!=)", body)) == 1, "assign newto exactly once"
expected = """
if (value == NULL) {
PyErr_SetString(PyExc_TypeError,
"can't delete __class__ attribute");
return -1;
}
if (!PyType_Check(value)) {
PyErr_Format(PyExc_TypeError,
"__class__ must be set to a class, not '%s' object",
Py_TYPE(value)->tp_name);
return -1;
}
newto = (PyTypeObject *)value;
if (PySys_Audit("object.__setattr__", "OsO",
self, "__class__", value) < 0) {
return -1;
}
"""
assert body[body.index("if (value == NULL)"):body.index("if (!(PyType_IsSubtype")].split() == expected.split(), (
"object_set_class: preserve rejection paths, cast after type validation, "
"and audit before compatibility checks"
)
print("object_set_class newto C89 declaration and evaluation timing: PASS")