Skip to content

Commit

Permalink
Cut ScopeConsumer (#9995)
Browse files Browse the repository at this point in the history
This class is only used by the NamesConsumer. It adds an extra level
of indirection, but without providing any clear benefit.
  • Loading branch information
nickdrozd authored Oct 1, 2024
1 parent 74c49b2 commit 3097f0b
Showing 1 changed file with 26 additions and 49 deletions.
75 changes: 26 additions & 49 deletions pylint/checkers/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from collections import defaultdict
from enum import Enum
from functools import cached_property
from typing import TYPE_CHECKING, NamedTuple
from typing import TYPE_CHECKING

import astroid
import astroid.exceptions
Expand All @@ -33,7 +33,6 @@

if TYPE_CHECKING:
from collections.abc import Generator, Iterable, Iterator
from typing import Any

from astroid.nodes import _base_nodes
from astroid.typing import InferenceResult
Expand Down Expand Up @@ -475,72 +474,49 @@ def _has_locals_call_after_node(stmt: nodes.NodeNG, scope: nodes.FunctionDef) ->
}


class ScopeConsumer(NamedTuple):
"""Store nodes and their consumption states."""
class NamesConsumer:
"""A simple class to handle consumed, to consume and scope type info of node locals."""

node: nodes.NodeNG
scope_type: str

to_consume: Consumption
consumed: Consumption
consumed_uncertain: Consumption
scope_type: str
"""Retrieves nodes filtered out by get_next_to_consume() that may not
have executed.
These include nodes such as statements in except blocks, or statements
in try blocks (when evaluating their corresponding except and finally
blocks). Checkers that want to treat the statements as executed
(e.g. for unused-variable) may need to add them back.
"""

class NamesConsumer:
"""A simple class to handle consumed, to consume and scope type info of node locals."""

def __init__(self, node: nodes.NodeNG, scope_type: str) -> None:
self._atomic = ScopeConsumer(
copy.copy(node.locals),
{},
defaultdict(list),
scope_type,
)
def __init__(self, node: nodes.NodeNG, scope_type: str):
self.node = node
self.scope_type = scope_type

self.to_consume = copy.copy(node.locals)
self.consumed = {}
self.consumed_uncertain = defaultdict(list)

self.names_under_always_false_test: set[str] = set()
self.names_defined_under_one_branch_only: set[str] = set()

def __repr__(self) -> str:
_to_consumes = [f"{k}->{v}" for k, v in self._atomic.to_consume.items()]
_consumed = [f"{k}->{v}" for k, v in self._atomic.consumed.items()]
_consumed_uncertain = [
f"{k}->{v}" for k, v in self._atomic.consumed_uncertain.items()
]
_to_consumes = [f"{k}->{v}" for k, v in self.to_consume.items()]
_consumed = [f"{k}->{v}" for k, v in self.consumed.items()]
_consumed_uncertain = [f"{k}->{v}" for k, v in self.consumed_uncertain.items()]
to_consumes = ", ".join(_to_consumes)
consumed = ", ".join(_consumed)
consumed_uncertain = ", ".join(_consumed_uncertain)
return f"""
to_consume : {to_consumes}
consumed : {consumed}
consumed_uncertain: {consumed_uncertain}
scope_type : {self._atomic.scope_type}
scope_type : {self.scope_type}
"""

def __iter__(self) -> Iterator[Any]:
return iter(self._atomic)

@property
def to_consume(self) -> Consumption:
return self._atomic.to_consume

@property
def consumed(self) -> Consumption:
return self._atomic.consumed

@property
def consumed_uncertain(self) -> Consumption:
"""Retrieves nodes filtered out by get_next_to_consume() that may not
have executed.
These include nodes such as statements in except blocks, or statements
in try blocks (when evaluating their corresponding except and finally
blocks). Checkers that want to treat the statements as executed
(e.g. for unused-variable) may need to add them back.
"""
return self._atomic.consumed_uncertain

@property
def scope_type(self) -> str:
return self._atomic.scope_type

def mark_as_consumed(self, name: str, consumed_nodes: list[nodes.NodeNG]) -> None:
"""Mark the given nodes as consumed for the name.
Expand Down Expand Up @@ -3314,7 +3290,8 @@ def _check_classdef_metaclasses(
name = METACLASS_NAME_TRANSFORMS.get(name, name)
if name:
# check enclosing scopes starting from most local
for scope_locals, _, _, _ in self._to_consume[::-1]:
for to_consume in self._to_consume[::-1]:
scope_locals = to_consume.to_consume
found_nodes = scope_locals.get(name, [])
for found_node in found_nodes:
if found_node.lineno <= klass.lineno:
Expand Down

0 comments on commit 3097f0b

Please sign in to comment.