diff options
author | Ćukasz Sznuk <ls@rdprojekt.pl> | 2017-07-17 15:29:23 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2017-07-19 16:20:11 +0200 |
commit | a53028da4f370e0ac94f4b11d74bdd2da2f1f610 (patch) | |
tree | d7ba794e70e838b8a2aa5d443f26743e8e746e3c | |
parent | 0fc0440b67935488e779ca2a8ab8ba6a407704f5 (diff) | |
download | pylint-git-a53028da4f370e0ac94f4b11d74bdd2da2f1f610.tar.gz |
Fix ifs in formatted strings crashing Pylint
-rw-r--r-- | pylint/checkers/refactoring.py | 22 | ||||
-rw-r--r-- | pylint/test/functional/formatted_string_literal_with_if_py36.py | 8 | ||||
-rw-r--r-- | pylint/test/functional/formatted_string_literal_with_if_py36.rc | 2 |
3 files changed, 19 insertions, 13 deletions
diff --git a/pylint/checkers/refactoring.py b/pylint/checkers/refactoring.py index 8bbdb902a..2ac7eefae 100644 --- a/pylint/checkers/refactoring.py +++ b/pylint/checkers/refactoring.py @@ -118,7 +118,6 @@ class RefactoringChecker(checkers.BaseTokenChecker): def _init(self): self._nested_blocks = [] self._elifs = [] - self._if_counter = 0 self._nested_blocks_msg = None @decorators.cachedproperty @@ -144,7 +143,7 @@ class RefactoringChecker(checkers.BaseTokenChecker): orelse = node.parent.orelse # current if node must directly follow a "else" if orelse and orelse == [node]: - if self._elifs[self._if_counter]: + if (node.lineno, node.col_offset) in self._elifs: return True return False @@ -208,9 +207,13 @@ class RefactoringChecker(checkers.BaseTokenChecker): for index, token in enumerate(tokens): token_string = token[1] if token_string == 'elif': - self._elifs.append(True) - elif token_string == 'if': - self._elifs.append(False) + # AST exists by the time process_tokens is called, so + # it's safe to assume tokens[index+1] + # exists. tokens[index+1][2] is the elif's position as + # reported by cPython, Jython and PyPy, + # tokens[index][2] is the actual position and also is + # reported by IronPython. + self._elifs.extend([tokens[index][2], tokens[index+1][2]]) elif six.PY3 and token.exact_type == tokenize.COMMA: self._check_one_element_trailing_comma_tuple(tokens, token, index) @@ -282,12 +285,6 @@ class RefactoringChecker(checkers.BaseTokenChecker): for name in names.nodes_of_class(astroid.AssignName): self._check_redefined_argument_from_local(name) - def visit_ifexp(self, _): - self._if_counter += 1 - - def visit_comprehension(self, node): - self._if_counter += len(node.ifs) - def _check_superfluous_else_return(self, node): if not node.orelse: # Not interested in if statements without else. @@ -302,7 +299,6 @@ class RefactoringChecker(checkers.BaseTokenChecker): self._check_simplifiable_if(node) self._check_nested_blocks(node) self._check_superfluous_else_return(node) - self._if_counter += 1 @utils.check_messages('too-many-nested-blocks') def leave_functiondef(self, _): @@ -329,7 +325,7 @@ class RefactoringChecker(checkers.BaseTokenChecker): break self._nested_blocks.pop() # if the node is a elif, this should not be another nesting level - if isinstance(node, astroid.If) and self._elifs[self._if_counter]: + if isinstance(node, astroid.If) and self._is_actual_elif(node): if self._nested_blocks: self._nested_blocks.pop() self._nested_blocks.append(node) diff --git a/pylint/test/functional/formatted_string_literal_with_if_py36.py b/pylint/test/functional/formatted_string_literal_with_if_py36.py new file mode 100644 index 000000000..8feb4e293 --- /dev/null +++ b/pylint/test/functional/formatted_string_literal_with_if_py36.py @@ -0,0 +1,8 @@ +"""Test that `if` in formatted string literal won't break Pylint.""" +# pylint: disable=missing-docstring, pointless-statement, using-constant-test + +f'{"+" if True else "-"}' +if True: + pass +elif True: + pass diff --git a/pylint/test/functional/formatted_string_literal_with_if_py36.rc b/pylint/test/functional/formatted_string_literal_with_if_py36.rc new file mode 100644 index 000000000..0ba2b6333 --- /dev/null +++ b/pylint/test/functional/formatted_string_literal_with_if_py36.rc @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.6 |