[Python-checkins] bpo-42128: Add __match_args__ to structseq-based classes (GH-24732)

pablogsal webhook-mailer at python.org
Wed Mar 3 19:03:51 EST 2021


https://github.com/python/cpython/commit/0632b1012d4dfa81ffef0d686a4710f6134f77a8
commit: 0632b1012d4dfa81ffef0d686a4710f6134f77a8
branch: master
author: Pablo Galindo <Pablogsal at gmail.com>
committer: pablogsal <Pablogsal at gmail.com>
date: 2021-03-04T00:03:44Z
summary:

bpo-42128: Add __match_args__ to structseq-based classes (GH-24732)

files:
A Misc/NEWS.d/next/Core and Builtins/2021-03-03-19-04-23.bpo-42128.VouZjn.rst
M Lib/test/test_structseq.py
M Objects/structseq.c

diff --git a/Lib/test/test_structseq.py b/Lib/test/test_structseq.py
index 36630a17367ff..a9fe193028ebe 100644
--- a/Lib/test/test_structseq.py
+++ b/Lib/test/test_structseq.py
@@ -122,5 +122,17 @@ def test_extended_getslice(self):
                     self.assertEqual(list(t[start:stop:step]),
                                      L[start:stop:step])
 
+    def test_match_args(self):
+        expected_args = ('tm_year', 'tm_mon', 'tm_mday', 'tm_hour', 'tm_min',
+                         'tm_sec', 'tm_wday', 'tm_yday', 'tm_isdst')
+        self.assertEqual(time.struct_time.__match_args__, expected_args)
+
+    def test_match_args_with_unnamed_fields(self):
+        expected_args = ('st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid',
+                         'st_gid', 'st_size')
+        self.assertEqual(os.stat_result.n_unnamed_fields, 3)
+        self.assertEqual(os.stat_result.__match_args__, expected_args)
+
+
 if __name__ == "__main__":
     unittest.main()
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-03-03-19-04-23.bpo-42128.VouZjn.rst b/Misc/NEWS.d/next/Core and Builtins/2021-03-03-19-04-23.bpo-42128.VouZjn.rst
new file mode 100644
index 0000000000000..7c4733a9b0d70
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-03-03-19-04-23.bpo-42128.VouZjn.rst	
@@ -0,0 +1,2 @@
+Add ``__match_args__`` to :c:type:`structsequence` based classes. Patch by
+Pablo Galindo.
diff --git a/Objects/structseq.c b/Objects/structseq.c
index 4222afa599c80..8a92bdbec08d1 100644
--- a/Objects/structseq.c
+++ b/Objects/structseq.c
@@ -15,6 +15,7 @@
 static const char visible_length_key[] = "n_sequence_fields";
 static const char real_length_key[] = "n_fields";
 static const char unnamed_fields_key[] = "n_unnamed_fields";
+static const char match_args_key[] = "__match_args__";
 
 /* Fields with this name have only a field index, not a field name.
    They are only allowed for indices < n_visible_fields. */
@@ -399,7 +400,40 @@ initialize_structseq_dict(PyStructSequence_Desc *desc, PyObject* dict,
     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__
+    Py_ssize_t i, k;
+    PyObject* keys = PyTuple_New(desc->n_in_sequence);
+    if (keys == NULL) {
+        return -1;
+    }
+
+    for (i = k = 0; i < desc->n_in_sequence; ++i) {
+        if (desc->fields[i].name == PyStructSequence_UnnamedField) {
+            continue;
+        }
+        PyObject* 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;
 }
 
 static void



More information about the Python-checkins mailing list