77 lines
2.2 KiB
Python
77 lines
2.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Keep find_name_in_mro mro/res C89-safe without changing lookup timing."""
|
|
import re
|
|
from pathlib import Path
|
|
|
|
source = Path("cpython/Objects/typeobject.c").read_text()
|
|
match = re.search(
|
|
r"\nfind_name_in_mro\(PyTypeObject \*type, PyObject \*name, int \*error\)\n"
|
|
r"\{(.*?)\n\}", source, re.S,
|
|
)
|
|
assert match, "find_name_in_mro definition missing"
|
|
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
|
|
assert re.match(r"\s*Py_hash_t hash;\s*PyObject \*mro;\s*PyObject \*res;\s*Py_ssize_t n;\s*(?:Py_ssize_t i;\s*)?if", body), (
|
|
"find_name_in_mro: mro and res must be declared at function entry (C89)"
|
|
)
|
|
assert not re.search(r"for\s*\(\s*Py_ssize_t\s+i\b", body), (
|
|
"find_name_in_mro: i remains declared in the for initializer (C89)"
|
|
)
|
|
expected = """
|
|
Py_hash_t hash;
|
|
PyObject *mro;
|
|
PyObject *res;
|
|
Py_ssize_t n;
|
|
Py_ssize_t i;
|
|
if (!PyUnicode_CheckExact(name) ||
|
|
(hash = _PyASCIIObject_CAST(name)->hash) == -1)
|
|
{
|
|
hash = PyObject_Hash(name);
|
|
if (hash == -1) {
|
|
*error = -1;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
mro = type->tp_mro;
|
|
if (mro == NULL) {
|
|
if ((type->tp_flags & Py_TPFLAGS_READYING) == 0) {
|
|
if (PyType_Ready(type) < 0) {
|
|
*error = -1;
|
|
return NULL;
|
|
}
|
|
mro = type->tp_mro;
|
|
}
|
|
if (mro == NULL) {
|
|
*error = 1;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
res = NULL;
|
|
|
|
Py_INCREF(mro);
|
|
n = PyTuple_GET_SIZE(mro);
|
|
for (i = 0; i < n; i++) {
|
|
PyObject *base = PyTuple_GET_ITEM(mro, i);
|
|
PyObject *dict = _PyType_CAST(base)->tp_dict;
|
|
assert(dict && PyDict_Check(dict));
|
|
res = _PyDict_GetItem_KnownHash(dict, name, hash);
|
|
if (res != NULL) {
|
|
break;
|
|
}
|
|
if (PyErr_Occurred()) {
|
|
*error = -1;
|
|
goto done;
|
|
}
|
|
}
|
|
*error = 0;
|
|
done:
|
|
Py_DECREF(mro);
|
|
return res;"""
|
|
assert body.split() == expected.split(), (
|
|
"find_name_in_mro: preserve hash/readiness checks, mro/res assignment timing, "
|
|
"reference handling, lookup, errors, and opening n/i declarations"
|
|
)
|
|
print("find_name_in_mro mro/res C89 declarations and same-point assignments: PASS")
|