Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

string.Formatter doesn't support empty curly braces "{}" #57807

Closed
RamchandraApte mannequin opened this issue Dec 14, 2011 · 30 comments
Closed

string.Formatter doesn't support empty curly braces "{}" #57807

RamchandraApte mannequin opened this issue Dec 14, 2011 · 30 comments
Assignees
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@RamchandraApte
Copy link
Mannequin

RamchandraApte mannequin commented Dec 14, 2011

BPO 13598
Nosy @terryjreedy, @vsajip, @ncoghlan, @ericvsmith, @mitsuhiko, @ezio-melotti, @merwok, @florentx, @meadori, @pelson
Files
  • issue13598.diff: A patch to fix this issue (Version 2)
  • test_string.diff: A patch to test.test_string to test for this bug.
  • issue13598.diff: A patch to fix this issue (Version 3)
  • issue13598.diff: A patch to fix this issue (Version 4)
  • test_string.diff: A patch to test.test_string to test for this bug. (Version 2)
  • pelson_issue13598.diff: An alternative patch to fix the issue (test included). (vn1)
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/ericvsmith'
    closed_at = <Date 2014-04-14.20:45:35.986>
    created_at = <Date 2011-12-14.03:59:21.793>
    labels = ['type-bug', 'library']
    title = 'string.Formatter doesn\'t support empty curly braces "{}"'
    updated_at = <Date 2014-05-08.14:46:39.380>
    user = 'https://bugs.python.org/RamchandraApte'

    bugs.python.org fields:

    activity = <Date 2014-05-08.14:46:39.380>
    actor = 'aronacher'
    assignee = 'eric.smith'
    closed = True
    closed_date = <Date 2014-04-14.20:45:35.986>
    closer = 'eric.smith'
    components = ['Library (Lib)']
    creation = <Date 2011-12-14.03:59:21.793>
    creator = 'Ramchandra Apte'
    dependencies = []
    files = ['23952', '23955', '24542', '25816', '25817', '27810']
    hgrepos = []
    issue_num = 13598
    keywords = ['patch']
    message_count = 30.0
    messages = ['149420', '149424', '149426', '149433', '149515', '149523', '149566', '150507', '153397', '153532', '153533', '162207', '162224', '162226', '162254', '162549', '162550', '162551', '162562', '162565', '162668', '174272', '174282', '180281', '180290', '183434', '183453', '216207', '216208', '218114']
    nosy_count = 13.0
    nosy_names = ['terry.reedy', 'vinay.sajip', 'ncoghlan', 'eric.smith', 'aronacher', 'ezio.melotti', 'eric.araujo', 'flox', 'meador.inge', 'python-dev', 'Ramchandra Apte', 'pelson', 'binkert']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue13598'
    versions = ['Python 3.5']

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Dec 14, 2011

    string.Formatter doesn't support empty curly braces "{}" unlike str.format .

    >>> import string
    >>> a = string.Formatter()
    >>> a.format("{}","test")
    Traceback (most recent call last):
      File "<pyshell#2>", line 1, in <module>
        a.format("{}","hello")
      File "/usr/lib/python3.2/string.py", line 180, in format
        return self.vformat(format_string, args, kwargs)
      File "/usr/lib/python3.2/string.py", line 184, in vformat
        result = self._vformat(format_string, args, kwargs, used_args, 2)
      File "/usr/lib/python3.2/string.py", line 206, in _vformat
        obj, arg_used = self.get_field(field_name, args, kwargs)
      File "/usr/lib/python3.2/string.py", line 267, in get_field
        obj = self.get_value(first, args, kwargs)
      File "/usr/lib/python3.2/string.py", line 226, in get_value
        return kwargs[key]
    KeyError: ''

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Dec 14, 2011

    Attached is patch to fix this issue.

    @RamchandraApte RamchandraApte mannequin added type-bug An unexpected behavior, bug, or error stdlib Python modules in the Lib dir labels Dec 14, 2011
    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Dec 14, 2011

    Sorry, the patch has an mistake.
    ValueErro should be ValueError.

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Dec 14, 2011

    Attached is a patch for test.test_string to test for this bug.
    Can somebody please comment on my paches or commit my patches.

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Dec 15, 2011

    Why isn't anybody commiting or commenting on my patches?

    @RamchandraApte RamchandraApte mannequin added stale Stale PR or inactive for long period of time. and removed stale Stale PR or inactive for long period of time. labels Dec 15, 2011
    @ericvsmith
    Copy link
    Member

    This bug is assigned to me. Sometimes it takes a while before a committer has time to review a bug and act on it. I can assure you that I will review this before the next release of Python.

    Thank you for the bug report, and especially thanks for the patch!

    One thing that will definitely need to be developed before this is committed is one or more tests. Either you can add them, or I will before I commit the fix. There are some existing tests for str.format that can be leveraged for string.Formatter.

    @meadori
    Copy link
    Member

    meadori commented Dec 15, 2011

    On Thu, Dec 15, 2011 at 1:42 AM, maniram maniram <report@bugs.python.org> wrote:

    Why isn't anybody commiting or commenting on my patches?

    Your patch is much appreciated. Thank you. It takes some time to get
    things reviewed. Please read the Dev Guide. In particular, the
    "Lifecycle of a Patch"
    section: http://docs.python.org/devguide/patch.html.

    Also, please quit marking issues as "languishing" unless the issue meets the
    qualifications spelled out here:
    http://docs.python.org/devguide/languishing.html.

    @merwok
    Copy link
    Member

    merwok commented Jan 3, 2012

    test_string.diff looks good, except that it should probably only test the exception type, not the message (they are not a guaranteed part of the Python language and may change arbitrarily between versions or implementations (e.g. PyPy), so better not to add tests that depend on exact words).

    I don’t have anything specific to say about bpo-13598.diff; if it makes the test pass, then it’s good. “if manual == True” should just be replaced by “if manual”.

    If you’d like to, you can make one patch with fix + tests that addresses my comments and remove the older diffs.

    @ncoghlan
    Copy link
    Contributor

    One potential problem with the simple approach to fixing this is that up until now, string.Formatter has been thread safe. Because all the formatting state was held in local variables and passed around as method arguments, there was no state on the instance object to protect.

    Now, this only applies if you start using the new feature, but it should be noted in the documentation and What's New that you need to limit yourself to accessing each formatter instance from a single thread.

    It's also enough for me to say "no, not in a maintenance release".

    Adding two attributes also seems unnecessary, and the pre-increment looks strange. Why not:

    In __init__:
    auto_field_count = 0

    Then as the auto numbering checking, something like:

        auto_field_count = self.auto_field_count
        if field_name:
            if auto_field_count > 0:
               # Can't switch auto -> manual
            auto_field_count = -1
        elif auto_field_count < 0:
           # Can't switch manual -> auto
        else:
            field_name = str(auto_field_count)
            self.auto_field_count += 1

    (Alternatively, I'd ask the question: why do we prevent mixing manual numbering and explicit numbering anyway? It's not like it's ambiguous at all)

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Feb 17, 2012

    @nick I don't understand why should my patch make Formatter thread-unsafe - the auto_field_count and manual variables are local variables just like the variables in the other functions in Formatter.

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Feb 17, 2012

    I have submitted a new patch, I have moved the increment to the end of if loop.

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Jun 3, 2012

    What is the status of the bug?

    @merwok
    Copy link
    Member

    merwok commented Jun 3, 2012

    Could you upload just one patch with fix and test, addressing my previous comments, and remove the old patches? It will make it easier for Eric to review when he gets some time. Please also keep lines under 80 characters. Thanks in advance.

    @vsajip
    Copy link
    Member

    vsajip commented Jun 3, 2012

    It seems like the patch doesn't consider mixing of positional and keyword arguments: if you have the format string "{foo} {} {bar}", then manual will be set to True when "foo" is seen as the field_name, and fail soon after when "" is seen as the field_name the next time around.

    So, the test should include something which shows that

    fmt.format("{foo} {} {bar}", 2, foo='fooval', bar='barval') returns "fooval 2 barval", whereas with a format string like "{foo} {0} {} {bar}" or "{foo} {} {0} {bar}" you get a ValueError.

    Also, why "automatic field numbering" vs. "manual field specification"? Why not "numbering" for both?

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Jun 4, 2012

    Added a new patch which addresses Éric's comments.

    @ericvsmith
    Copy link
    Member

    Is there a reason "manual" is None, True, or False? Wouldn't just True or False suffice?

    @vsajip
    Copy link
    Member

    vsajip commented Jun 8, 2012

    Is there a reason "manual" is None, True, or False? Wouldn't just True or False suffice?

    I suppose before we see the first bracketed form ({} or {\d+}) we don't know which it is.

    @ericvsmith
    Copy link
    Member

    Yes, I guess that's so. I'll have to add a comment, as at first glance it just looks like a bug. Thanks!

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Jun 9, 2012

    Its not a bug though it has maintenance problems because if you change "manual is False" to not manual it no longer works correctly.

    @vsajip
    Copy link
    Member

    vsajip commented Jun 9, 2012

    it has maintenance problems because if you change "manual is False"
    to not manual it no longer works correctly.

    So you should probably comment the initialisation appropriately.

    @ncoghlan
    Copy link
    Contributor

    One brief comment on the wording of the error message: the inconsistent naming is actually copied from the str.format code.

    >>> "{foo} {} {bar}".format(2, foo='fooval', bar='barval')
    'fooval 2 barval'
    >>> "{foo} {0} {} {bar}".format(2, foo='fooval', bar='barval')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: cannot switch from manual field specification to automatic field numbering

    @pelson
    Copy link
    Mannequin

    pelson mannequin commented Oct 31, 2012

    The current patch fails to catch the fact that auto vs manual numbering has been used in following corner case:

    from string import Formatter
    print(Formatter().format("{0:{}}", 'foo', 5))

    To fix this, without adding state to the formatter instance, some more information is going to need to be passed to the _vformat method.

    @pelson
    Copy link
    Mannequin

    pelson mannequin commented Oct 31, 2012

    Ramchandra's fix looks fairly good, although there is at least one remaining issue (see my last comment). I have attached a patch which addresses (and tests) this.

    I'd be happy to pick this up if there are any remaining issues that need to be addressed, otherwise: I hope this helps.

    Thanks,

    @RamchandraApte
    Copy link
    Mannequin Author

    RamchandraApte mannequin commented Jan 20, 2013

    Buump.

    @vsajip
    Copy link
    Member

    vsajip commented Jan 20, 2013

    Looking at Phil Elson's patch:

    I didn't see a test case relating to the example in his comment, namely

    f.format("{0:{}}", 'foo', 5)

    Did I miss it? The documentation also needs to be updated.

    @pelson
    Copy link
    Mannequin

    pelson mannequin commented Mar 4, 2013

    I didn't see a test case relating to the example in his comment, namely

    f.format("{0:{}}", 'foo', 5)

    Did I miss it?

    The example should fail, which it wouldn't have done with the patch previously proposed. I believe the case is covered by the block:

        with self.assertRaises(ValueError):
            fmt.format("foo{1}{}", "bar", 6)

    Though there is no harm in adding another test along the lines of:

        with self.assertRaises(ValueError):
            fmt.format("{0:{}}", "bar", 6)

    If you think it is worthwhile?

    I'm uncertain which documentation to update since the method which has had its signature updated is private and is called solely by Formatter.vformat .

    Cheers,

    @vsajip
    Copy link
    Member

    vsajip commented Mar 4, 2013

    I believe the case is covered by the block:
    [snip]

    Ah, right. I wasn't sure that was the exact same code path that was being exercised. But I didn't look very closely.

    If you think it is worthwhile?

    Only if it exercises a different code path.

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Apr 14, 2014

    New changeset ad74229a6fba by Eric V. Smith in branch '3.4':
    Issue bpo-13598: Add auto-numbering of replacement fields to string.Formatter.
    http://hg.python.org/cpython/rev/ad74229a6fba

    @python-dev
    Copy link
    Mannequin

    python-dev mannequin commented Apr 14, 2014

    New changeset 50fe497983fd by Eric V. Smith in branch '3.4':
    Issue bpo-13598: Added acknowledgements to Misc/NEWS.
    http://hg.python.org/cpython/rev/50fe497983fd

    @mitsuhiko
    Copy link
    Member

    Is there any chance this will be fixed for 2.7 as well?

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    6 participants