summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2019-09-30 09:40:05 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2019-09-30 09:40:05 +0200
commit552fa8a26c5f5f6c7661697bc4c9c835c3b7daa3 (patch)
tree5941aa860fec6a7bb4f5a9964d5bc79b0527547f
parent4ec293ce4700bfaca89d01c45e707f40c2913d49 (diff)
downloadpylint-git-552fa8a26c5f5f6c7661697bc4c9c835c3b7daa3.tar.gz
Fix ``utils.is_error`` to account for functions returning early.
This fixes a false negative with ``unused-variable`` which was no longer triggered when a function raised an exception as the last instruction, but the body of the function still had unused variables. Close #3028
-rw-r--r--ChangeLog8
-rw-r--r--pylint/checkers/utils.py10
-rw-r--r--tests/functional/u/unused_variable.py7
-rw-r--r--tests/functional/u/unused_variable.txt1
4 files changed, 23 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 5189034a2..76beb4ba8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,14 @@ Release date: TBA
Close #3141
+* Fix ``utils.is_error`` to account for functions returning early.
+
+ This fixes a false negative with ``unused-variable`` which was no longer triggered
+ when a function raised an exception as the last instruction, but the body of the function
+ still had unused variables.
+
+ Close #3028
+
What's New in Pylint 2.4.1?
===========================
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index def655769..22c44836a 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -266,10 +266,14 @@ def is_super(node: astroid.node_classes.NodeNG) -> bool:
def is_error(node: astroid.node_classes.NodeNG) -> bool:
"""return true if the function does nothing but raising an exception"""
- for child_node in node.get_children():
+ raises = False
+ returns = False
+ for child_node in node.nodes_of_class((astroid.Raise, astroid.Return)):
if isinstance(child_node, astroid.Raise):
- return True
- return False
+ raises = True
+ if isinstance(child_node, astroid.Return):
+ returns = True
+ return raises and not returns
builtins = builtins.__dict__.copy() # type: ignore
diff --git a/tests/functional/u/unused_variable.py b/tests/functional/u/unused_variable.py
index cb5215d99..2d2c540b9 100644
--- a/tests/functional/u/unused_variable.py
+++ b/tests/functional/u/unused_variable.py
@@ -58,3 +58,10 @@ def unused_import_from():
def unused_import_in_function(value):
from six import PY2, text_type # [unused-import]
return value.encode("utf-8") if PY2 else value
+
+
+def hello(arg):
+ my_var = 'something' # [unused-variable]
+ if arg:
+ return True
+ raise Exception
diff --git a/tests/functional/u/unused_variable.txt b/tests/functional/u/unused_variable.txt
index e9f7ef022..635324529 100644
--- a/tests/functional/u/unused_variable.txt
+++ b/tests/functional/u/unused_variable.txt
@@ -11,3 +11,4 @@ unused-variable:46:locals_does_not_account_for_subscopes:Unused variable 'value'
unused-import:54:unused_import_from:Unused wraps imported from functools as abc
unused-import:55:unused_import_from:Unused namedtuple imported from collections
unused-import:59:unused_import_in_function:Unused text_type imported from six
+unused-variable:64:hello:Unused variable 'my_var'