Files
Python3-Win9x/scripts/vc6-classobject-typeinit.test.py

50 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Verify legacy MSVC gets runtime-assigned classobject type fields."""
import sys
from pathlib import Path
if len(sys.argv) != 3:
raise SystemExit("usage: vc6-classobject-typeinit.test.py classobject.c object.c")
class_source = Path(sys.argv[1]).read_text()
object_source = Path(sys.argv[2]).read_text()
legacy_condition = "!defined(MS_WINDOWS) || !defined(_MSC_VER) || _MSC_VER >= 1300"
for symbol in ("PyMethod_Type", "PyInstanceMethod_Type"):
start = class_source.index("PyTypeObject " + symbol + " = {")
end = class_source.index("\n};", start)
initializer = class_source[start:end]
if "#if " + legacy_condition not in initializer:
raise SystemExit(symbol + " designated initializer must be excluded for VC6 Windows")
start = object_source.index("_PyTypes_InitTypes(PyInterpreterState *interp)")
body_start = object_source.index("\n{\n", start) + 2
body_end = object_source.index("\n}\n", body_start)
body = object_source[body_start:body_end]
ready = body.index("PyType_Ready(type)")
call = body.index("_PyClassObject_InitTypes();")
if call > ready:
raise SystemExit("legacy type fields must be initialized before PyType_Ready")
helper = class_source.index("_PyClassObject_InitTypes(void)")
helper_body_start = class_source.index("\n{\n", helper) + 2
helper_body_end = class_source.index("\n}\n", helper_body_start)
helper_body = class_source[helper_body_start:helper_body_end]
assignments = {
"PyMethod_Type": (
"tp_name", "tp_basicsize", "tp_dealloc", "tp_vectorcall_offset", "tp_repr",
"tp_hash", "tp_call", "tp_getattro", "tp_setattro", "tp_flags", "tp_doc",
"tp_traverse", "tp_richcompare", "tp_weaklistoffset", "tp_methods", "tp_members",
"tp_getset", "tp_new",
),
"PyInstanceMethod_Type": (
"tp_name", "tp_basicsize", "tp_dealloc", "tp_repr", "tp_call", "tp_getattro",
"tp_setattro", "tp_flags", "tp_doc", "tp_traverse", "tp_richcompare",
"tp_members", "tp_getset", "tp_descr_get", "tp_new",
),
}
for symbol, fields in assignments.items():
for field in fields:
assignment = symbol + "." + field + " ="
if assignment not in helper_body:
raise SystemExit("missing legacy setup assignment " + assignment)
print("classobject VC6 type initialization coverage: PASS")