From 6b66ca65b2c8e4562d5550694ba68bb6bb445034 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 6 Jun 2024 23:30:27 +0200 Subject: [PATCH] [undefined-variable] Fix a crash for undefined lineno in annotations (#9705) (#9706) (cherry picked from commit f082174bc7f111e4e411b74a00e1cf9aa231ce39) Co-authored-by: Pierre Sassoulas --- doc/whatsnew/fragments/8866.bugfix | 3 +++ pylint/checkers/variables.py | 15 ++++++++------- .../functional/u/undefined/undefined_variable.py | 4 ++++ .../functional/u/undefined/undefined_variable.txt | 1 + 4 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 doc/whatsnew/fragments/8866.bugfix diff --git a/doc/whatsnew/fragments/8866.bugfix b/doc/whatsnew/fragments/8866.bugfix new file mode 100644 index 0000000000..2eba31dccb --- /dev/null +++ b/doc/whatsnew/fragments/8866.bugfix @@ -0,0 +1,3 @@ +Fixed a crash when the lineno of a variable used as an annotation wasn't available for ``undefined-variable``. + +Closes #8866 diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 8447320b89..8e8b0e0bfb 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -2295,13 +2295,14 @@ def _is_variable_violation( # using a name defined earlier in the class containing the function. if node is frame.returns and defframe.parent_of(frame.returns): annotation_return = True - if ( - frame.returns.name in defframe.locals - and defframe.locals[node.name][0].lineno < frame.lineno - ): - # Detect class assignments with a name defined earlier in the - # class. In this case, no warning should be raised. - maybe_before_assign = False + if frame.returns.name in defframe.locals: + definition = defframe.locals[node.name][0] + if definition.lineno is None or definition.lineno < frame.lineno: + # Detect class assignments with a name defined earlier in the + # class. In this case, no warning should be raised. + maybe_before_assign = False + else: + maybe_before_assign = True else: maybe_before_assign = True if isinstance(node.parent, nodes.Arguments): diff --git a/tests/functional/u/undefined/undefined_variable.py b/tests/functional/u/undefined/undefined_variable.py index 194de114d3..19c134e77b 100644 --- a/tests/functional/u/undefined/undefined_variable.py +++ b/tests/functional/u/undefined/undefined_variable.py @@ -380,3 +380,7 @@ def y(self) -> RepeatedReturnAnnotations: # [undefined-variable] pass def z(self) -> RepeatedReturnAnnotations: # [undefined-variable] pass + +class A: + def say_hello(self) -> __module__: # [undefined-variable] + ... diff --git a/tests/functional/u/undefined/undefined_variable.txt b/tests/functional/u/undefined/undefined_variable.txt index ea707c910a..c527c76d96 100644 --- a/tests/functional/u/undefined/undefined_variable.txt +++ b/tests/functional/u/undefined/undefined_variable.txt @@ -37,3 +37,4 @@ undefined-variable:365:10:365:20:global_var_mixed_assignment:Undefined variable undefined-variable:377:19:377:44:RepeatedReturnAnnotations.x:Undefined variable 'RepeatedReturnAnnotations':UNDEFINED undefined-variable:379:19:379:44:RepeatedReturnAnnotations.y:Undefined variable 'RepeatedReturnAnnotations':UNDEFINED undefined-variable:381:19:381:44:RepeatedReturnAnnotations.z:Undefined variable 'RepeatedReturnAnnotations':UNDEFINED +undefined-variable:385:27:385:37:A.say_hello:Undefined variable '__module__':UNDEFINED