Skip to content

Commit

Permalink
Fix FP for possibly-used-before-assignment with assert_never() (#…
Browse files Browse the repository at this point in the history
…9645) (#9647)

(cherry picked from commit 117be95)

Co-authored-by: Jacob Walls <[email protected]>
Co-authored-by: Pierre Sassoulas <[email protected]>
  • Loading branch information
3 people authored May 18, 2024
1 parent 9dae975 commit aed496a
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 7 deletions.
4 changes: 4 additions & 0 deletions doc/whatsnew/fragments/9643.false_positive
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix a false positive for `possibly-used-before-assignment` when using
`typing.assert_never()` (3.11+) to indicate exhaustiveness.

Closes #9643
17 changes: 10 additions & 7 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
is_sys_guard,
overridden_method,
)
from pylint.constants import PY39_PLUS, TYPING_NEVER, TYPING_NORETURN
from pylint.constants import PY39_PLUS, PY311_PLUS, TYPING_NEVER, TYPING_NORETURN
from pylint.interfaces import CONTROL_FLOW, HIGH, INFERENCE, INFERENCE_FAILURE
from pylint.typing import MessageDefinitionTuple

Expand Down Expand Up @@ -940,12 +940,15 @@ def _uncertain_nodes_in_except_blocks(
def _defines_name_raises_or_returns(name: str, node: nodes.NodeNG) -> bool:
if isinstance(node, (nodes.Raise, nodes.Assert, nodes.Return, nodes.Continue)):
return True
if (
isinstance(node, nodes.Expr)
and isinstance(node.value, nodes.Call)
and utils.is_terminating_func(node.value)
):
return True
if isinstance(node, nodes.Expr) and isinstance(node.value, nodes.Call):
if utils.is_terminating_func(node.value):
return True
if (
PY311_PLUS
and isinstance(node.value.func, nodes.Name)
and node.value.func.name == "assert_never"
):
return True
if (
isinstance(node, nodes.AnnAssign)
and node.value
Expand Down
1 change: 1 addition & 0 deletions pylint/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
PY38_PLUS = sys.version_info[:2] >= (3, 8)
PY39_PLUS = sys.version_info[:2] >= (3, 9)
PY310_PLUS = sys.version_info[:2] >= (3, 10)
PY311_PLUS = sys.version_info[:2] >= (3, 11)
PY312_PLUS = sys.version_info[:2] >= (3, 12)

IS_PYPY = platform.python_implementation() == "PyPy"
Expand Down
21 changes: 21 additions & 0 deletions tests/functional/u/used/used_before_assignment_py311.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""assert_never() introduced in 3.11"""
from enum import Enum
from typing import assert_never


class MyEnum(Enum):
"""A lovely enum."""
VAL1 = 1
VAL2 = 2


def do_thing(val: MyEnum) -> None:
"""Do a thing."""
if val is MyEnum.VAL1:
note = 'got 1'
elif val is MyEnum.VAL2:
note = 'got 2'
else:
assert_never(val)

print('Note:', note)
2 changes: 2 additions & 0 deletions tests/functional/u/used/used_before_assignment_py311.rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[testoptions]
min_pyver=3.11

0 comments on commit aed496a

Please sign in to comment.