Skip to content

Commit

Permalink
Bug pylint 4122 (#4304)
Browse files Browse the repository at this point in the history
* Adds detection of return type hint to determine if a function has NoReturn
* Adds unittests to check return type hints are correctly interpreted
* Adds an entry
* Adds argparse.parse_error as default for never-returning-functions option
* Simplification of NoReturn detection as suggested by cdce8p
  • Loading branch information
hippo91 authored Apr 7, 2021
1 parent 07df776 commit 4168e80
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 1 deletion.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ Release date: Undefined
..
Put bug fixes that will be cherry-picked to latest major version here

* Functions that never returns may declare ``NoReturn`` as type hints, so that
``inconsistent-return-statements`` is not emitted.

Closes #4122, #4188

* Improved protected access checks to allow access inside class methods

Closes #1159
Expand Down
9 changes: 8 additions & 1 deletion pylint/checkers/refactoring/refactoring_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
(
"never-returning-functions",
{
"default": ("sys.exit",),
"default": ("sys.exit", "argparse.parse_error"),
"type": "csv",
"help": "Complete name of functions that never returns. When checking "
"for inconsistent-return-statements if a never returning function is "
Expand Down Expand Up @@ -1405,6 +1405,13 @@ def _is_function_def_never_returning(self, node: astroid.FunctionDef) -> bool:
Returns:
bool: True if the function never returns, False otherwise.
"""
if isinstance(node, astroid.FunctionDef) and node.returns:
return (
isinstance(node.returns, astroid.Attribute)
and node.returns.attrname == "NoReturn"
or isinstance(node.returns, astroid.Name)
and node.returns.name == "NoReturn"
)
try:
return node.qname() in self._never_returning_functions
except TypeError:
Expand Down
52 changes: 52 additions & 0 deletions tests/functional/i/inconsistent/inconsistent_returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,3 +335,55 @@ def bug_pylint_3873_2():
except IndexError:
nothing_to_do()
return False

import typing # pylint: disable=wrong-import-position

def parser_error(msg) -> typing.NoReturn: #pylint:disable=unused-argument
sys.exit(1)

def parser_error_nortype(msg): #pylint:disable=unused-argument
sys.exit(2)


from typing import NoReturn # pylint: disable=wrong-import-position

def parser_error_name(msg) -> NoReturn: #pylint:disable=unused-argument
sys.exit(3)

def bug_pylint_4122(s):
"""
Every returns is consistent because parser_error has type hints
indicating it never returns
"""
try:
n = int(s)
if n < 1:
raise ValueError()
return n
except ValueError:
parser_error('parser error')

def bug_pylint_4122_wrong(s): # [inconsistent-return-statements]
"""
Every returns is not consistent because parser_error_nortype has no type hints
"""
try:
n = int(s)
if n < 1:
raise ValueError()
return n
except ValueError:
parser_error_nortype('parser error')

def bug_pylint_4122_bis(s):
"""
Every returns is consistent because parser_error has type hints
indicating it never returns
"""
try:
n = int(s)
if n < 1:
raise ValueError()
return n
except ValueError:
parser_error_name('parser error')
1 change: 1 addition & 0 deletions tests/functional/i/inconsistent/inconsistent_returns.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ inconsistent-return-statements:262:8:bug_1794_inner_func_in_if_counter_example_3
inconsistent-return-statements:267:0:bug_3468:Either all return statements in a function should return an expression, or none of them should.
inconsistent-return-statements:277:0:bug_3468_variant:Either all return statements in a function should return an expression, or none of them should.
inconsistent-return-statements:322:0:bug_pylint_3873_1:Either all return statements in a function should return an expression, or none of them should.
inconsistent-return-statements:366:0:bug_pylint_4122_wrong:Either all return statements in a function should return an expression, or none of them should.

0 comments on commit 4168e80

Please sign in to comment.