8000 gh-71494: string.Formatter: support keys/attributes in unnumbered fie… · python/cpython@22b2d37 · GitHub
[go: up one dir, main page]

Skip to content

Commit 22b2d37

Browse files
authored
gh-71494: string.Formatter: support keys/attributes in unnumbered fields (GH-21767)
1 parent 0373926 commit 22b2d37

File tree

3 files changed

+28
-7
lines changed
  • Lib
    • < 8000 div class="PRIVATE_VisuallyHidden prc-TreeView-TreeViewVisuallyHidden-4-mPv" aria-hidden="true" id=":R1ddddabH1:">
      string.py
  • test
  • Misc/NEWS.d/next/Library
  • 3 files changed

    +28
    -7
    lines changed

    Lib/string.py

    Lines changed: 8 additions & 7 deletions
    Original file line numberDiff line numberDiff line change
    @@ -212,19 +212,20 @@ def _vformat(self, format_string, args, kwargs, used_args, recursion_depth,
    212212
    # this is some markup, find the object and do
    213213
    # the formatting
    214214

    215-
    # handle arg indexing when empty field_names are given.
    216-
    if field_name == '':
    215+
    # handle arg indexing when empty field first parts are given.
    216+
    field_first, _ = _string.formatter_field_name_split(field_name)
    217+
    if field_first == '':
    217218
    if auto_arg_index is False:
    218219
    raise ValueError('cannot switch from manual field '
    219220
    'specification to automatic field '
    220221
    'numbering')
    221-
    field_name = str(auto_arg_index)
    222+
    field_name = str(auto_arg_index) + field_name
    222223
    auto_arg_index += 1
    223-
    elif field_name.isdigit():
    224+
    elif isinstance(field_first, int):
    224225
    if auto_arg_index:
    225-
    raise ValueError('cannot switch from manual field '
    226-
    'specification to automatic field '
    227-
    'numbering')
    226+
    raise ValueError('cannot switch from automatic field '
    227+
    'numbering to manual field '
    228+
    'specification')
    228229
    # disable auto arg incrementing, if it gets
    229230
    # used later on, then an exception will be raised
    230231
    auto_arg_index = False

    Lib/test/test_string.py

    Lines changed: 19 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,7 @@
    11
    import unittest
    22
    import string
    33
    from string import Template
    4+
    import types
    45

    56

    67
    class ModuleTest(unittest.TestCase):
    @@ -101,6 +102,24 @@ def test_index_lookup(self):
    101102
    with self.assertRaises(KeyError):
    102103
    fmt.format("{0[2]}{0[0]}", {})
    103104

    105+
    def test_auto_numbering_lookup(self):
    106+
    fmt = string.Formatter()
    107+
    namespace = types.SimpleNamespace(foo=types.SimpleNamespace(bar='baz'))
    108+
    widths = [None, types.SimpleNamespace(qux=4)]
    109+
    self.assertEqual(
    110+
    fmt.format("{.foo.bar:{[1].qux}}", namespace, widths), 'baz ')
    111+
    112+
    def test_auto_numbering_reenterability(self):
    113+
    class ReenteringFormatter(string.Formatter):
    114+
    def format_field(self, value, format_spec):
    115+
    if format_spec.isdigit() and int(format_spec) > 0:
    116+
    return self.format('{:{}}!', value, int(format_spec) - 1)
    117+
    else:
    118+
    return super().format_field(value, format_spec)
    119+
    fmt = ReenteringFormatter()
    120+
    x = types.SimpleNamespace(a='X')
    121+
    self.assertEqual(fmt.format('{.a:{}}', x, 3), 'X!!!')
    122+
    104123
    def test_override_get_value(self):
    105124
    class NamespaceFormatter(string.Formatter):
    106125
    def __init__(self, namespace={}):
    Lines changed: 1 addition & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -0,0 +1 @@
    1+
    Add attribute and item access support to :class:`string.Formatter` in auto-numbering mode, which allows format strings like '{.name}' and '{[1]}'.

    0 commit comments

    Comments
     (0)
    0