port: advance VC6 compatibility frontier
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
#!/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")
|
||||
Reference in New Issue
Block a user