85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Check initialize_structseq_dict's C89 declarations and operation order."""
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
source = Path(sys.argv[1] if len(sys.argv) > 1 else "cpython/Objects/structseq.c")
|
|
match = re.search(
|
|
r"static int\ninitialize_structseq_dict\(.*?\) \{(.*?)\n\}",
|
|
source.read_text(),
|
|
re.S,
|
|
)
|
|
assert match, "initialize_structseq_dict definition not found"
|
|
body = match.group(1)
|
|
assert re.match(
|
|
r"\s*PyObject \*v;\s*Py_ssize_t i, k;\s*PyObject\* keys;", body
|
|
), "i, k, and uninitialized keys must precede all statements for C89"
|
|
assert re.search(
|
|
r"for \(i = k = 0; i < desc->n_in_sequence; \+\+i\) \{"
|
|
r"\s*PyObject\* new_member;\s*if", body
|
|
), "uninitialized new_member must precede the loop's unnamed-field check for C89"
|
|
|
|
expected = r"""
|
|
PyObject *v;
|
|
Py_ssize_t i, k;
|
|
PyObject* keys;
|
|
|
|
#define SET_DICT_FROM_SIZE(key, value) \
|
|
do { \
|
|
v = PyLong_FromSsize_t(value); \
|
|
if (v == NULL) { \
|
|
return -1; \
|
|
} \
|
|
if (PyDict_SetItemString(dict, key, v) < 0) { \
|
|
Py_DECREF(v); \
|
|
return -1; \
|
|
} \
|
|
Py_DECREF(v); \
|
|
} while (0)
|
|
|
|
SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
|
|
SET_DICT_FROM_SIZE(real_length_key, n_members);
|
|
SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
|
|
|
|
// Prepare and set __match_args__
|
|
keys = PyTuple_New(desc->n_in_sequence);
|
|
if (keys == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
for (i = k = 0; i < desc->n_in_sequence; ++i) {
|
|
PyObject* new_member;
|
|
if (desc->fields[i].name == PyStructSequence_UnnamedField) {
|
|
continue;
|
|
}
|
|
new_member = PyUnicode_FromString(desc->fields[i].name);
|
|
if (new_member == NULL) {
|
|
goto error;
|
|
}
|
|
PyTuple_SET_ITEM(keys, k, new_member);
|
|
k++;
|
|
}
|
|
|
|
if (_PyTuple_Resize(&keys, k) == -1) {
|
|
goto error;
|
|
}
|
|
|
|
if (PyDict_SetItemString(dict, match_args_key, keys) < 0) {
|
|
goto error;
|
|
}
|
|
|
|
Py_DECREF(keys);
|
|
return 0;
|
|
|
|
error:
|
|
Py_DECREF(keys);
|
|
return -1;
|
|
"""
|
|
assert re.sub(r"\s+", "", body) == re.sub(r"\s+", "", expected), (
|
|
"preserve metadata writes and early returns before tuple allocation, skip "
|
|
"unnamed fields before Unicode allocation, and preserve insertion, resize, "
|
|
"match-args write, refcount, and cleanup order"
|
|
)
|
|
print("initialize_structseq_dict C89 declarations and operation order: PASS")
|