summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/whatsnew/fragments/8280.false_negative3
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py9
-rw-r--r--tests/functional/i/inconsistent/inconsistent_returns.py51
-rw-r--r--tests/functional/i/inconsistent/inconsistent_returns.txt2
4 files changed, 61 insertions, 4 deletions
diff --git a/doc/whatsnew/fragments/8280.false_negative b/doc/whatsnew/fragments/8280.false_negative
new file mode 100644
index 000000000..848b71d7c
--- /dev/null
+++ b/doc/whatsnew/fragments/8280.false_negative
@@ -0,0 +1,3 @@
+Fix false negative for inconsistent-returns with while-loops.
+
+Closes #8280
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index 0caa2fbb5..5aaedf794 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -20,6 +20,7 @@ from astroid.util import Uninferable
from pylint import checkers
from pylint.checkers import utils
+from pylint.checkers.base.basic_error_checker import _loop_exits_early
from pylint.checkers.utils import node_frame_class
from pylint.interfaces import HIGH, INFERENCE, Confidence
@@ -1945,10 +1946,12 @@ class RefactoringChecker(checkers.BaseTokenChecker):
return True
except astroid.InferenceError:
pass
- # Avoid the check inside while loop as we don't know
- # if they will be completed
if isinstance(node, nodes.While):
- return True
+ # A while-loop is considered return-ended if it has a
+ # truthy test and no break statements
+ return (node.test.bool_value() and not _loop_exits_early(node)) or any(
+ self._is_node_return_ended(child) for child in node.orelse
+ )
if isinstance(node, nodes.Raise):
return self._is_raise_node_return_ended(node)
if isinstance(node, nodes.If):
diff --git a/tests/functional/i/inconsistent/inconsistent_returns.py b/tests/functional/i/inconsistent/inconsistent_returns.py
index c1183b288..4e9a68377 100644
--- a/tests/functional/i/inconsistent/inconsistent_returns.py
+++ b/tests/functional/i/inconsistent/inconsistent_returns.py
@@ -1,5 +1,5 @@
#pylint: disable=missing-docstring, no-else-return, no-else-break, invalid-name, unused-variable, superfluous-parens, try-except-raise
-#pylint: disable=disallowed-name
+#pylint: disable=disallowed-name,too-few-public-methods,no-member,useless-else-on-loop
"""Testing inconsistent returns"""
import math
import sys
@@ -353,3 +353,52 @@ def bug_pylint_4019_wrong(x): # [inconsistent-return-statements]
if x == 1:
return 42
assert True
+
+
+# https://github.com/PyCQA/pylint/issues/8280
+class A:
+ def get_the_answer(self): # [inconsistent-return-statements]
+ while self.is_running:
+ self.read_message()
+ if self.comunication_finished():
+ return "done"
+
+
+def bug_1772_break(): # [inconsistent-return-statements]
+ counter = 1
+ while True:
+ counter += 1
+ if counter == 100:
+ return 7
+ if counter is None:
+ break
+
+
+def while_break_in_for():
+ counter = 1
+ while True:
+ counter += 1
+ if counter == 100:
+ return 7
+ for i in range(10):
+ if i == 5:
+ break
+
+
+def while_break_in_while():
+ counter = 1
+ while True:
+ counter += 1
+ if counter == 100:
+ return 7
+ while True:
+ if counter == 5:
+ break
+
+
+def wait_for_apps_ready(event, main_thread):
+ while main_thread.is_alive():
+ if event.wait(timeout=0.1):
+ return True
+ else:
+ return False
diff --git a/tests/functional/i/inconsistent/inconsistent_returns.txt b/tests/functional/i/inconsistent/inconsistent_returns.txt
index 8e67a83f8..125f3dec7 100644
--- a/tests/functional/i/inconsistent/inconsistent_returns.txt
+++ b/tests/functional/i/inconsistent/inconsistent_returns.txt
@@ -15,3 +15,5 @@ inconsistent-return-statements:267:0:267:12:bug_3468:Either all return statement
inconsistent-return-statements:277:0:277:20:bug_3468_variant:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED
inconsistent-return-statements:322:0:322:21:bug_pylint_3873_1:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED
inconsistent-return-statements:349:0:349:25:bug_pylint_4019_wrong:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED
+inconsistent-return-statements:360:4:360:22:A.get_the_answer:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED
+inconsistent-return-statements:367:0:367:18:bug_1772_break:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED