Skip to content

Commit

Permalink
Understand starred expression used in string formatting RHS tuple (#1299
Browse files Browse the repository at this point in the history
)

Fixes #957
  • Loading branch information
rogalski committed Feb 19, 2017
1 parent e0fdd25 commit 0d3b4a7
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 1 deletion.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ Release date: tba

Fixes #831

* `too-many-format-args` and `too-few-format-args` are emitted correctly when
starred expression are used in RHS tuple.

Fixes #957


What's new in Pylint 1.6.3?
===========================

Expand Down
10 changes: 10 additions & 0 deletions doc/whatsnew/2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,16 @@ Bug fixes
class MyError(Exception): pass
* `too-many-format-args` and `too-few-format-args` are emitted correctly
(or not emitted at all, when exact count of elements in RHS cannot be
inferred) when starred expressions are used in RHS tuple. For example,
code block as shown below detects correctly that the used tuple has in
fact three elements, not two.

.. code-block:: python
meat = ['spam', 'ham']
print('%s%s%s' % ('eggs', *meat))
Removed Changes
===============
Expand Down
5 changes: 4 additions & 1 deletion pylint/checkers/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,10 @@ def visit_binop(self, node):
# the % operator matches the number required by the format
# string.
if isinstance(args, astroid.Tuple):
num_args = len(args.elts)
rhs_tuple = utils.safe_infer(args)
num_args = None
if rhs_tuple not in (None, astroid.Uninferable):
num_args = len(rhs_tuple.elts)
elif isinstance(args, OTHER_NODES + (astroid.Dict, astroid.DictComp)):
num_args = 1
else:
Expand Down
21 changes: 21 additions & 0 deletions pylint/test/functional/string_formatting_py3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# pylint: disable=missing-docstring,import-error


def issue_957_good():
meat = ['spam', 'ham']
print('%s%s%s' % ('eggs', *meat))


def issue_957_bad1():
meat = ['spam', 'ham', 'monthy python']
print('%s%s%s' % ('eggs', *meat)) # [too-many-format-args]


def issue_957_bad2():
meat = ['spam']
print('%s%s%s' % ('eggs', *meat)) # [too-few-format-args]


def issue_957_uninferable():
from butchery import meat
print('%s%s%s' % ('eggs', *meat))
2 changes: 2 additions & 0 deletions pylint/test/functional/string_formatting_py3.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.0
2 changes: 2 additions & 0 deletions pylint/test/functional/string_formatting_py3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
too-many-format-args:11:issue_957_bad1:Too many arguments for format string
too-few-format-args:16:issue_957_bad2:Not enough arguments for format string

0 comments on commit 0d3b4a7

Please sign in to comment.