Bad-format pylint string explanation

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 peeling 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 proposal, pylint developers say that the check is done in the style of PEP 3101 , but I don’t see anything in the PEP, which is broken here.

What is the problem? What does the peelint want to do from us?

Version numbers are 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] 
+6
source share
1 answer

This is a bug in pylint ; he assumes that all string formats are byte strings.

Linter parses the format and then the placeholder names. Since you use Unicode literals, this also creates a unicode name, but the parser makes the assumption that it will only encounter bittests; if not, he assumes he will find an integer:

 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 results in a ValueError for your format string, since world parsed for unicode value:

 >>> 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, in turn, is caught and converted to an IncompleteFormatString exception, which then leads to error W1302 .

See the parse_format_method_string function.

The test there must be modified to check the same type as format_string :

 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 will do the right thing in both Python 2 and 3.

+3
source

Source: https://habr.com/ru/post/973159/


All Articles