Files
Python3-Win9x/scripts/vc6-typeobject-type-new-get-bases-winner-c89.test.py
T

92 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""Check winner's C89 declaration and preserve get-bases evaluation order."""
import re
from pathlib import Path
source = Path("cpython/Objects/typeobject.c").read_text()
match = re.search(
r"\nstatic int\ntype_new_get_bases\(type_new_ctx \*ctx, PyObject \*\*type\)\n\{(.*?)\n\}",
source, re.S,
)
assert match, "type_new_get_bases definition missing"
body = re.sub(r"/\*.*?\*/|//[^\n]*", "", match.group(1), flags=re.S)
assert re.match(
r"\s*Py_ssize_t nbases = PyTuple_GET_SIZE\(ctx->bases\);"
r"\s*Py_ssize_t i;\s*PyTypeObject \*winner;\s*PyTypeObject \*base;"
r"\s*if \(nbases == 0\)",
body,
), "type_new_get_bases: winner must be declared before statements (C89)"
assert len(re.findall(r"\bPyTypeObject\s*\*\s*winner\b", body)) == 1, (
"declare winner exactly once"
)
expected = """
Py_ssize_t nbases = PyTuple_GET_SIZE(ctx->bases);
Py_ssize_t i;
PyTypeObject *base;
if (nbases == 0) {
PyObject *new_bases;
ctx->base = &PyBaseObject_Type;
new_bases = PyTuple_Pack(1, ctx->base);
if (new_bases == NULL) {
return -1;
}
ctx->bases = new_bases;
return 0;
}
for (i = 0; i < nbases; i++) {
PyObject *base = PyTuple_GET_ITEM(ctx->bases, i);
PyObject *mro_entries;
if (PyType_Check(base)) {
continue;
}
if (_PyObject_LookupAttr(base, &_Py_ID(__mro_entries__),
&mro_entries) < 0) {
return -1;
}
if (mro_entries != NULL) {
PyErr_SetString(PyExc_TypeError,
"type() doesn't support MRO entry resolution; "
"use types.new_class()");
Py_DECREF(mro_entries);
return -1;
}
}
winner = _PyType_CalculateMetaclass(ctx->metatype, ctx->bases);
if (winner == NULL) {
return -1;
}
if (winner != ctx->metatype) {
if (winner->tp_new != type_new) {
*type = winner->tp_new(winner, ctx->args, ctx->kwds);
if (*type == NULL) {
return -1;
}
return 1;
}
ctx->metatype = winner;
}
base = best_base(ctx->bases);
if (base == NULL) {
return -1;
}
ctx->base = base;
ctx->bases = Py_NewRef(ctx->bases);
return 0;
"""
without_winner_declaration = re.sub(r"\bPyTypeObject\s*\*\s*winner;", "", body)
assert without_winner_declaration.split() == expected.split(), (
"preserve base validation, metaclass calculation, winner dispatch, best-base "
"calculation, reference updates, and returns at their original evaluation points"
)
print("type_new_get_bases winner C89 declaration and evaluation ordering: PASS")