mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +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
	
	 Pablo Galindo
						Pablo Galindo