classification
Title: '' % [1] doesn't fail
Type: Stage:
Components: Versions:
process
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: asvetlov, bakuriu, eric.smith, r.david.murray, serhiy.storchaka, vstinner
Priority: normal Keywords:

Created on 2013-08-15 17:10 by asvetlov, last changed 2013-09-01 12:39 by asvetlov. This issue is now closed.

Messages (12)
msg195263 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2013-08-15 17:10
I think this is a bug.
Can be reproduced on all Pythons (from 2.6 to 3.4a).
Maybe should be fixed for 3.4 only as backward incompatible change.
msg195268 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-08-15 18:14
What is it that doesn't fail?  The expression in the title is the beginning of a triple quoted string with no closing triple quote.

If you mean '' % [1] not falling, it has been that way forever (well, python2.4 is as far back as I can test), so if it is deemed worth changing it certainly should not be backported.

I suspect it is some consequence of the C level similarities between lists and dicts, since '' % {<anything>} is supposed to not produce an error.
msg195269 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2013-08-15 18:18
I don't understand why str % list and str % dict behaves differently than str % int:

>>> 'abc' % [1]
'abc'
>>> 'abc' % ([1],)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
>>> 'abc' % 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
>>> 'abc' % {1:2}
'abc'
>>> 'abc' % ({1:2},)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: not all arguments converted during string formatting
msg195272 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-08-15 18:34
haypo: str % dict is a feature:

  >>> "%(a)s" % {'a': 1, 'b': 2}
  '1'
msg195273 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2013-08-15 18:38
For dict it is correct from my perspective.
"" % {'a': 'b'}
tries to substitute format specs like "%(a)s" and does nothing if spec is not present.

But list case like
"" % [1]
confuse me.
msg195281 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-08-15 19:48
Yes, I suspect you are right that that is a bug...and a long standing one :)
msg195309 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2013-08-16 04:04
Objects/unicodeobject.c has this, at line 14316:

    if (PyMapping_Check(args) && !PyTuple_Check(args) && !PyUnicode_Check(args))
        ctx.dict = args;
    else
        ctx.dict = NULL;

and later at line 14348:
    if (ctx.argidx < ctx.arglen && !ctx.dict) {
        PyErr_SetString(PyExc_TypeError,
                        "not all arguments converted during string formatting");
        goto onError;
    }

Because list now returns true for PyMapping_Check, this code thinks the list is a dict and skips the error.

There's some discussion of PyMapping_Check in issue 5945.
msg195326 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-08-16 13:24
Hmm.  The linked issue says the PyMappingCheck behavior is new in Python3, but this problem exists in Python2 (back to 2.4 at least) as well.  Perhaps it is a different bug in Python2.
msg195329 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2013-08-16 13:31
The code looks basically the same in 2.7, and there PyMapping_Check looks for __getitem__, so maybe issue 5945 is just incorrect in its analysis.

In any event, I'm not sure this is worth fixing. There are lots of little corner cases that could be broken.
msg195629 - (view) Author: Giacomo Alzetta (bakuriu) Date: 2013-08-19 13:04
Note that the documentation for formatting with %, found here: http://docs.python.org/2/library/stdtypes.html#string-formatting-operations,  states:

"""
If format requires a single argument, values may be a single non-tuple object. [5] Otherwise, values must be a tuple with exactly the number of items specified by the format string, or a single mapping object (for example, a dictionary)."""

Note how it explicitly states that in an expression: format % value there are two different cases:

 - If format contains *exactly one* format specifier, then value can be any non-tuple item and it will be formatted as is. Otherwise, value MUST be either tuple or a mapping.

In your example '' contains 0 format specifiers, hence you MUST use either a tuple or a dict. Any other object triggers "undefined behaviour"(in particular depending on whether the object define __geitem__ or not the formatting might or might not raise an exception etc.)

AFAIK only few people know this, hence changing the code could potentially break a lot of code for apparently no reason.
Since people should start to move to str.format instead of % this wart may not be worth fixing.
msg195656 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2013-08-19 18:52
> Since people should start to move to str.format instead of % this wart may not be worth fixing.

>>> ''.format_map([1])
''

However I agree that this is not worth fixing.
msg196719 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2013-09-01 12:39
Ok. Close as won't fix.
Please reopen if needed.
History
Date User Action Args
2013-09-01 12:39:11asvetlovsetstatus: open -> closed
resolution: wont fix
messages: + msg196719
2013-08-19 18:52:27serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg195656
2013-08-19 13:04:45bakuriusetnosy: + bakuriu
messages: + msg195629
2013-08-16 13:31:06eric.smithsetmessages: + msg195329
2013-08-16 13:24:28r.david.murraysetmessages: + msg195326
2013-08-16 04:04:56eric.smithsettitle: '' % [1] doens't fail -> '' % [1] doesn't fail
2013-08-16 04:04:02eric.smithsetnosy: + eric.smith
messages: + msg195309
2013-08-15 19:48:00r.david.murraysetmessages: + msg195281
2013-08-15 18:38:05asvetlovsetmessages: + msg195273
2013-08-15 18:34:53r.david.murraysetmessages: + msg195272
2013-08-15 18:18:01vstinnersetnosy: + vstinner

messages: + msg195269
title: ''' % [1] doens't fail -> '' % [1] doens't fail
2013-08-15 18:14:13r.david.murraysetnosy: + r.david.murray
messages: + msg195268
2013-08-15 17:10:56asvetlovcreate