diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2014-07-29 02:41:50 +0300 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2014-07-29 02:41:50 +0300 |
commit | 78ed1eb83bb75ea1582d69b0b3bb0ba9cadfdbe3 (patch) | |
tree | 728fe3fbf49244f013651fbdbf3118b71183518a | |
parent | 7c86e39440a6d3469237b2f478ff50dca949ed02 (diff) | |
download | pylint-git-78ed1eb83bb75ea1582d69b0b3bb0ba9cadfdbe3.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-- | ChangeLog | 5 | ||||
-rw-r--r-- | checkers/strings.py | 23 | ||||
-rw-r--r-- | test/input/func_string_format_py27.py | 2 | ||||
-rw-r--r-- | test/messages/func_string_format_py27.txt | 2 |
4 files changed, 22 insertions, 10 deletions
@@ -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 8251a80cc..a07482a8e 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 d2f5599be..38eafd13a 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 56f8c4126..c94e953f2 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
|