summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcpopa <devnull@localhost>2014-07-29 02:41:50 +0300
committercpopa <devnull@localhost>2014-07-29 02:41:50 +0300
commitbe5921dd65f379f2dbdbd0f32d546bde9d517403 (patch)
treeaa99472002b527de43ee2befab8755eed7f444fa
parentd4b715c69ae9ac2da43f555e3d92b7339a96e368 (diff)
downloadpylint-be5921dd65f379f2dbdbd0f32d546bde9d517403.tar.gz
Fix a false positive with string formatting checker, when encountering a string which uses only position-based arguments. Closes issue #285.
-rw-r--r--ChangeLog5
-rw-r--r--checkers/strings.py23
-rw-r--r--test/input/func_string_format_py27.py2
-rw-r--r--test/messages/func_string_format_py27.txt2
4 files changed, 22 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 47b255f..4bef070 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
ChangeLog for Pylint
====================
+--
+ * Fix a false positive with string formatting checker, when
+ encountering a string which uses only position-based arguments.
+ Closes issue #285.
+
2014-07-26 -- 1.3.0
* Allow hanging continued indentation for implicitly concatenated
diff --git a/checkers/strings.py b/checkers/strings.py
index 8251a80..a07482a 100644
--- a/checkers/strings.py
+++ b/checkers/strings.py
@@ -136,12 +136,14 @@ else:
def parse_format_method_string(format_string):
"""
Parses a PEP 3101 format string, returning a tuple of
- (keys, num_args),
- where keys is the set of mapping keys in the format string and num_args
- is the number of arguments required by the format string.
+ (keys, num_args, manual_pos_arg),
+ where keys is the set of mapping keys in the format string, num_args
+ is the number of arguments required by the format string and
+ manual_pos_arg is the number of arguments passed with the position.
"""
keys = []
num_args = 0
+ manual_pos_arg = 0
formatter = string.Formatter()
parseiterator = formatter.parse(format_string)
try:
@@ -150,7 +152,9 @@ def parse_format_method_string(format_string):
# not a replacement format
continue
name = result[1]
- if name:
+ if name and str(name).isdigit():
+ manual_pos_arg += 1
+ elif name:
keyname, fielditerator = split_format_field_names(name)
if not isinstance(keyname, str):
# In Python 2 it will return long which will lead
@@ -163,7 +167,7 @@ def parse_format_method_string(format_string):
# probably the format string is invalid
# should we check the argument of the ValueError?
raise utils.IncompleteFormatString(format_string)
- return keys, num_args
+ return keys, num_args, manual_pos_arg
def get_args(callfunc):
""" Get the arguments from the given `CallFunc` node.
@@ -327,7 +331,7 @@ class StringMethodsChecker(BaseChecker):
except astroid.InferenceError:
return
try:
- fields, num_args = parse_format_method_string(strnode.value)
+ fields, num_args, manual_pos = parse_format_method_string(strnode.value)
except utils.IncompleteFormatString:
self.add_message('bad-format-string', node=node)
return
@@ -336,7 +340,7 @@ class StringMethodsChecker(BaseChecker):
if isinstance(field[0], int))
named_fields = set(field[0] for field in fields
if isinstance(field[0], str))
- if manual_fields and num_args:
+ if num_args and manual_pos:
self.add_message('format-combined-specification',
node=node)
return
@@ -353,6 +357,8 @@ class StringMethodsChecker(BaseChecker):
node=node,
args=(field, ))
else:
+ # num_args can be 0 if manual_pos is not.
+ num_args = num_args or manual_pos
if positional > num_args:
# We can have two possibilities:
# * "{0} {1}".format(a, b)
@@ -363,9 +369,6 @@ class StringMethodsChecker(BaseChecker):
elif positional < num_args:
self.add_message('too-few-format-args', node=node)
- if manual_fields and positional < len(manual_fields):
- self.add_message('too-few-format-args', node=node)
-
self._check_new_format_specifiers(node, fields, named)
def _check_new_format_specifiers(self, node, fields, named):
diff --git a/test/input/func_string_format_py27.py b/test/input/func_string_format_py27.py
index d2f5599..38eafd1 100644
--- a/test/input/func_string_format_py27.py
+++ b/test/input/func_string_format_py27.py
@@ -76,3 +76,5 @@ def pprint_bad():
print "{a[0]}".format(a=object)
print log("{}".format(2, "info"))
print "{0.missing}".format(2)
+ print "{0} {1} {2}".format(1, 2)
+ print "{0} {1}".format(1, 2, 3)
diff --git a/test/messages/func_string_format_py27.txt b/test/messages/func_string_format_py27.txt
index 56f8c41..c94e953 100644
--- a/test/messages/func_string_format_py27.txt
+++ b/test/messages/func_string_format_py27.txt
@@ -3,6 +3,8 @@ E: 64:pprint_bad: Not enough arguments for format string
E: 65:pprint_bad: Too many arguments for format string
E: 67:pprint_bad: Not enough arguments for format string
E: 77:pprint_bad: Too many arguments for format string
+E: 79:pprint_bad: Not enough arguments for format string
+E: 80:pprint_bad: Too many arguments for format string
W: 59:pprint_bad: Invalid format string
W: 60:pprint_bad: Invalid format string
W: 61:pprint_bad: Format string contains both automatic field numbering and manual field specification