In the following file:
"""hello I am the module spam.py"""
from __future__ import unicode_literals
'hello {world}'.format(world='potato')
We have the following pylint violation for bad-format-string
:
wim@SDFA100461C:/tmp$ pylint --reports=n spam.py
No config file found, using default configuration
************* Module spam
W: 3, 0: Invalid format string (bad-format-string)
I don't understand this suggestion, pylint devs say the check is about PEP 3101 style but I don't see anything in the PEP which is violated here.
What is the problem? What does pylint wish us to do about it?
Version numbers below.
wim@SDFA100461C:/tmp$ pylint --version
No config file found, using default configuration
pylint 1.3.0,
astroid 1.2.0, common 0.62.1
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2]
This is a bug in pylint
; it assumes that all string formats are byte strings.
The linter parses the format and then the placeholder names. Because you are using Unicode literals, this produces a unicode
name too, but the parser makes the assumption that it'll only encounter bytestrings; if not, it assumes it found an integer instead:
if not isinstance(keyname, str):
# In Python 2 it will return long which will lead
# to different output between 2 and 3
keyname = int(keyname)
This raises a ValueError
for your format string as world
is parsed to a unicode
value instead:
>>> import string
>>> formatter = string.Formatter()
>>> parseiterator = formatter.parse(u'hello {world}')
>>> result = next(parseiterator)
>>> result
(u'hello ', u'world', u'', None)
>>> keyname, fielditerator = result[1]._formatter_field_name_split()
>>> keyname
u'world'
The ValueError
exception then in turn is caught and converted to a IncompleteFormatString
exception, which then results in the W1302
error code.
See the parse_format_method_string
function.
The test there should be altered to test for the same type as format_string
instead:
if not isinstance(keyname, type(format_string)):
# In Python 2 it will return long which will lead
# to different output between 2 and 3
keyname = int(keyname)
This'll do the correct thing in both Python 2 and 3.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With