Skip to content

Commit 0632b10

Browse files
authored
bpo-42128: Add __match_args__ to structseq-based classes (GH-24732)
1 parent 9c79274 commit 0632b10

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

‎Lib/test/test_structseq.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,5 +122,17 @@ def test_extended_getslice(self):
122122
self.assertEqual(list(t[start:stop:step]),
123123
L[start:stop:step])
124124

125+
def test_match_args(self):
126+
expected_args = ('tm_year', 'tm_mon', 'tm_mday', 'tm_hour', 'tm_min',
127+
'tm_sec', 'tm_wday', 'tm_yday', 'tm_isdst')
128+
self.assertEqual(time.struct_time.__match_args__, expected_args)
129+
130+
def test_match_args_with_unnamed_fields(self):
131+
expected_args = ('st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid',
132+
'st_gid', 'st_size')
133+
self.assertEqual(os.stat_result.n_unnamed_fields, 3)
134+
self.assertEqual(os.stat_result.__match_args__, expected_args)
135+
136+
125137
if __name__ == "__main__":
126138
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ``__match_args__`` to :c:type:`structsequence` based classes. Patch by
2+
Pablo Galindo.

‎Objects/structseq.c‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
static const char visible_length_key[] = "n_sequence_fields";
1616
static const char real_length_key[] = "n_fields";
1717
static const char unnamed_fields_key[] = "n_unnamed_fields";
18+
static const char match_args_key[] = "__match_args__";
1819

1920
/* Fields with this name have only a field index, not a field name.
2021
They are only allowed for indices < n_visible_fields. */
@@ -399,7 +400,40 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict,
399400
SET_DICT_FROM_SIZE(visible_length_key, desc->n_in_sequence);
400401
SET_DICT_FROM_SIZE(real_length_key, n_members);
401402
SET_DICT_FROM_SIZE(unnamed_fields_key, n_unnamed_members);
403+
404+
// Prepare and set __match_args__
405+
Py_ssize_t i, k;
406+
PyObject* keys = PyTuple_New(desc->n_in_sequence);
407+
if (keys == NULL) {
408+
return -1;
409+
}
410+
411+
for (i = k = 0; i < desc->n_in_sequence; ++i) {
412+
if (desc->fields[i].name == PyStructSequence_UnnamedField) {
413+
continue;
414+
}
415+
PyObject* new_member = PyUnicode_FromString(desc->fields[i].name);
416+
if (new_member == NULL) {
417+
goto error;
418+
}
419+
PyTuple_SET_ITEM(keys, k, new_member);
420+
k++;
421+
}
422+
423+
if (_PyTuple_Resize(&keys, k) == -1) {
424+
goto error;
425+
}
426+
427+
if (PyDict_SetItemString(dict, match_args_key, keys) < 0) {
428+
goto error;
429+
}
430+
431+
Py_DECREF(keys);
402432
return 0;
433+
434+
error:
435+
Py_DECREF(keys);
436+
return -1;
403437
}
404438

405439
static void

0 commit comments

Comments
 (0)