mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	bpo-42128: Add __match_args__ to structseq-based classes (GH-24732)
This commit is contained in:
		
							parent
							
								
									9c7927400c
								
							
						
					
					
						commit
						0632b1012d
					
				
					 3 changed files with 48 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
Add ``__match_args__`` to :c:type:`structsequence` based classes. Patch by
 | 
			
		||||
Pablo Galindo.
 | 
			
		||||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue