Skip to content

Commit

Permalink
Revise filtering logic
Browse files Browse the repository at this point in the history
  • Loading branch information
zenlyj committed Oct 5, 2024
1 parent 95337f3 commit b404520
Showing 1 changed file with 30 additions and 34 deletions.
64 changes: 30 additions & 34 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,17 @@ def get_next_to_consume(self, node: nodes.Name) -> list[nodes.NodeNG] | None:
uncertain_nodes_set = set(uncertain_nodes)
found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]

if found_nodes:
type_checking_nodes = [n for n in found_nodes if in_type_checking_block(n)]
uncertain_nodes_set = set(type_checking_nodes)
# Add type_checking nodes to the list of uncertains if they are not already present

Check notice on line 628 in pylint/checkers/variables.py

View workflow job for this annotation

GitHub Actions / pylint

C0401

Wrong spelling of a word 'uncertains' in a comment:
self.consumed_uncertain[node.name] += [
n
for n in type_checking_nodes
if n not in self.consumed_uncertain[node.name]
]
found_nodes = [n for n in found_nodes if n not in uncertain_nodes_set]

return found_nodes

def _inferred_to_define_name_raise_or_return(
Expand Down Expand Up @@ -721,7 +732,9 @@ def _uncertain_nodes_if_tests(
for other_node in found_nodes:
if isinstance(other_node, nodes.AssignName):
name = other_node.name
elif isinstance(other_node, (nodes.Import, nodes.ImportFrom)):
elif isinstance(
other_node, (nodes.Import, nodes.ImportFrom)
) and not in_type_checking_block(other_node):
name = node.name
else:
continue
Expand Down Expand Up @@ -1763,13 +1776,15 @@ def _check_consumer(
if found_nodes is None:
return (VariableVisitConsumerAction.CONTINUE, None)
if not found_nodes:
is_reported = self._report_unfound_name_definition(node, current_consumer)
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, is_reported
)
nodes_to_consume = [
n
for n in current_consumer.consumed_uncertain[node.name]
if not in_type_checking_block(n)
]

return (
VariableVisitConsumerAction.RETURN,
nodes_to_consume,
Expand Down Expand Up @@ -1942,24 +1957,24 @@ def _report_unfound_name_definition(
self,
node: nodes.NodeNG,
current_consumer: NamesConsumer,
) -> bool:
) -> None:
"""Reports used-before-assignment when all name definition nodes
get filtered out by NamesConsumer.
"""
if (
self._postponed_evaluation_enabled
and utils.is_node_in_type_annotation_context(node)
):
return False
return
if self._is_builtin(node.name):
return False
return
if self._is_variable_annotation_in_function(node):
return False
return
if (
node.name in self._evaluated_type_checking_scopes
and node.scope() in self._evaluated_type_checking_scopes[node.name]
):
return False
return

confidence = HIGH
if node.name in current_consumer.names_under_always_false_test:
Expand All @@ -1979,34 +1994,15 @@ 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.
"""
type_checking_import = next(
(
n
for n in nodes_to_consume
if isinstance(n, (nodes.Import, nodes.ImportFrom))
and in_type_checking_block(n)
),
None,
)
# If used-before-assignment reported for usage of type checking import
# keep track of its scope
if type_checking_import and is_reported:
if node.name in current_consumer.consumed_uncertain and any(
in_type_checking_block(n)
for n in current_consumer.consumed_uncertain[node.name]
):
self._evaluated_type_checking_scopes.setdefault(node.name, []).append(
node.scope()
)
nodes_to_consume = [n for n in nodes_to_consume if n != type_checking_import]
return nodes_to_consume

@utils.only_required_for_messages("no-name-in-module")
def visit_import(self, node: nodes.Import) -> None:
Expand Down

0 comments on commit b404520

Please sign in to comment.