diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index a996dc3277..3352c17c2a 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -1787,12 +1787,12 @@ def _check_consumer( if found_nodes is None: return (VariableVisitConsumerAction.CONTINUE, None) if not found_nodes: - self._report_unfound_name_definition(node, current_consumer) + is_reported = self._report_unfound_name_definition(node, current_consumer) # Mark for consumption any nodes added to consumed_uncertain by # get_next_to_consume() because they might not have executed. nodes_to_consume = current_consumer.consumed_uncertain[node.name] nodes_to_consume = self._filter_type_checking_import_from_consumption( - node, nodes_to_consume + node, nodes_to_consume, is_reported ) return ( VariableVisitConsumerAction.RETURN, @@ -1966,7 +1966,7 @@ def _report_unfound_name_definition( self, node: nodes.NodeNG, current_consumer: NamesConsumer, - ) -> None: + ) -> bool: """Reports used-before-assignment when all name definition nodes get filtered out by NamesConsumer. """ @@ -1974,16 +1974,16 @@ def _report_unfound_name_definition( self._postponed_evaluation_enabled and utils.is_node_in_type_annotation_context(node) ): - return + return False if self._is_builtin(node.name): - return + return False if self._is_variable_annotation_in_function(node): - return + return False if ( node.name in self._evaluated_type_checking_scopes and node.scope() in self._evaluated_type_checking_scopes[node.name] ): - return + return False confidence = HIGH if node.name in current_consumer.names_under_always_false_test: @@ -2003,10 +2003,13 @@ def _report_unfound_name_definition( confidence=confidence, ) + return True + def _filter_type_checking_import_from_consumption( self, node: nodes.NodeNG, nodes_to_consume: list[nodes.NodeNG], + is_reported: bool ) -> list[nodes.NodeNG]: """Do not consume type-checking import node as used-before-assignment may invoke in different scopes. @@ -2022,7 +2025,7 @@ def _filter_type_checking_import_from_consumption( ) # If used-before-assignment reported for usage of type checking import # keep track of its scope - if type_checking_import and not self._is_variable_annotation_in_function(node): + if type_checking_import and is_reported: self._evaluated_type_checking_scopes.setdefault(node.name, []).append( node.scope() ) diff --git a/tests/functional/u/used/used_before_assignment_scoping.py b/tests/functional/u/used/used_before_assignment_scoping.py index 0d88210bdd..5443cc7441 100644 --- a/tests/functional/u/used/used_before_assignment_scoping.py +++ b/tests/functional/u/used/used_before_assignment_scoping.py @@ -1,5 +1,6 @@ # pylint: disable=missing-function-docstring, missing-module-docstring +from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: @@ -15,4 +16,4 @@ def func(): first: datetime first = datetime.now() # [used-before-assignment] second = datetime.now() - return first, second + return first, second \ No newline at end of file diff --git a/tests/functional/u/used/used_before_assignment_scoping.txt b/tests/functional/u/used/used_before_assignment_scoping.txt index 007f59a27c..0a297919f9 100644 --- a/tests/functional/u/used/used_before_assignment_scoping.txt +++ b/tests/functional/u/used/used_before_assignment_scoping.txt @@ -1,2 +1,4 @@ -used-before-assignment:10:13:10:21:func_two:Using variable 'datetime' before assignment:INFERENCE -used-before-assignment:16:12:16:20:func:Using variable 'datetime' before assignment:INFERENCE +used-before-assignment:11:13:11:21:func_two:Using variable 'datetime' before assignment:INFERENCE +used-before-assignment:17:12:17:20:func:Using variable 'datetime' before assignment:INFERENCE +used-before-assignment:23:11:23:19:x:Using variable 'datetime' before assignment:INFERENCE +used-before-assignment:28:12:28:20:Z.something:Using variable 'datetime' before assignment:INFERENCE