mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 21:51:50 +00:00 
			
		
		
		
	gh-71494: string.Formatter: support keys/attributes in unnumbered fields (GH-21767)
This commit is contained in:
		
							parent
							
								
									0373926260
								
							
						
					
					
						commit
						22b2d37f42
					
				
					 3 changed files with 28 additions and 7 deletions
				
			
		|  | @ -212,19 +212,20 @@ def _vformat(self, format_string, args, kwargs, used_args, recursion_depth, | |||
|                 # this is some markup, find the object and do | ||||
|                 #  the formatting | ||||
| 
 | ||||
|                 # handle arg indexing when empty field_names are given. | ||||
|                 if field_name == '': | ||||
|                 # handle arg indexing when empty field first parts are given. | ||||
|                 field_first, _ = _string.formatter_field_name_split(field_name) | ||||
|                 if field_first == '': | ||||
|                     if auto_arg_index is False: | ||||
|                         raise ValueError('cannot switch from manual field ' | ||||
|                                          'specification to automatic field ' | ||||
|                                          'numbering') | ||||
|                     field_name = str(auto_arg_index) | ||||
|                     field_name = str(auto_arg_index) + field_name | ||||
|                     auto_arg_index += 1 | ||||
|                 elif field_name.isdigit(): | ||||
|                 elif isinstance(field_first, int): | ||||
|                     if auto_arg_index: | ||||
|                         raise ValueError('cannot switch from manual field ' | ||||
|                                          'specification to automatic field ' | ||||
|                                          'numbering') | ||||
|                         raise ValueError('cannot switch from automatic field ' | ||||
|                                          'numbering to manual field ' | ||||
|                                          'specification') | ||||
|                     # disable auto arg incrementing, if it gets | ||||
|                     # used later on, then an exception will be raised | ||||
|                     auto_arg_index = False | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| import unittest | ||||
| import string | ||||
| from string import Template | ||||
| import types | ||||
| 
 | ||||
| 
 | ||||
| class ModuleTest(unittest.TestCase): | ||||
|  | @ -101,6 +102,24 @@ def test_index_lookup(self): | |||
|         with self.assertRaises(KeyError): | ||||
|             fmt.format("{0[2]}{0[0]}", {}) | ||||
| 
 | ||||
|     def test_auto_numbering_lookup(self): | ||||
|         fmt = string.Formatter() | ||||
|         namespace = types.SimpleNamespace(foo=types.SimpleNamespace(bar='baz')) | ||||
|         widths = [None, types.SimpleNamespace(qux=4)] | ||||
|         self.assertEqual( | ||||
|             fmt.format("{.foo.bar:{[1].qux}}", namespace, widths), 'baz ') | ||||
| 
 | ||||
|     def test_auto_numbering_reenterability(self): | ||||
|         class ReenteringFormatter(string.Formatter): | ||||
|             def format_field(self, value, format_spec): | ||||
|                 if format_spec.isdigit() and int(format_spec) > 0: | ||||
|                     return self.format('{:{}}!', value, int(format_spec) - 1) | ||||
|                 else: | ||||
|                     return super().format_field(value, format_spec) | ||||
|         fmt = ReenteringFormatter() | ||||
|         x = types.SimpleNamespace(a='X') | ||||
|         self.assertEqual(fmt.format('{.a:{}}', x, 3), 'X!!!') | ||||
| 
 | ||||
|     def test_override_get_value(self): | ||||
|         class NamespaceFormatter(string.Formatter): | ||||
|             def __init__(self, namespace={}): | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| Add attribute and item access support to :class:`string.Formatter` in auto-numbering mode, which allows format strings like '{.name}' and '{[1]}'. | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 qm2k
						qm2k