diff --git a/flake8_type_checking/checker.py b/flake8_type_checking/checker.py index 0689a5b..0e917c0 100644 --- a/flake8_type_checking/checker.py +++ b/flake8_type_checking/checker.py @@ -19,7 +19,6 @@ ANNOTATION_PROPERTY, ATTRIBUTE_PROPERTY, ATTRS_DECORATORS, - ATTRS_IMPORTS, BINOP_OPERAND_PROPERTY, MISSING, TC001, @@ -53,7 +52,6 @@ HasPosition, Import, ImportTypeValue, - Name, SupportsIsTyping, ) @@ -130,53 +128,19 @@ class AttrsMixin: """ if TYPE_CHECKING: - third_party_imports: dict[str, Import] - def get_all_attrs_imports(self) -> dict[str | None, str]: - """Return a map of all attrs/attr imports.""" - attrs_imports: dict[str | None, str] = {} # map of alias to full import name - - for node in self.third_party_imports.values(): - module = getattr(node, 'module', '') - names: list[Name] = getattr(node, 'names', []) - - for name in names: - if module in ATTRS_IMPORTS: - alias = name.name if name.asname is None else name.asname - attrs_imports[alias] = f'{module}.{name.name}' - elif name.name.split('.')[0] in ATTRS_IMPORTS: - attrs_imports[name.asname] = name.name - - return attrs_imports + def lookup_full_name(self, node: ast.AST) -> str | None: # noqa: D102 + ... def is_attrs_class(self, class_node: ast.ClassDef) -> bool: """Check whether an ast.ClassDef is an attrs class or not.""" - attrs_imports = self.get_all_attrs_imports() - return any(self.is_attrs_decorator(decorator, attrs_imports) for decorator in class_node.decorator_list) + return any(self.is_attrs_decorator(decorator) for decorator in class_node.decorator_list) - def is_attrs_decorator(self, decorator: Any, attrs_imports: dict[str | None, str]) -> bool: + def is_attrs_decorator(self, decorator: ast.AST) -> bool: """Check whether a class decorator is an attrs decorator or not.""" if isinstance(decorator, ast.Call): - return self.is_attrs_decorator(decorator.func, attrs_imports) - elif isinstance(decorator, ast.Attribute): - return self.is_attrs_attribute(decorator) - elif isinstance(decorator, ast.Name): - return self.is_attrs_str(decorator.id, attrs_imports) - return False - - @staticmethod - def is_attrs_attribute(attribute: ast.Attribute) -> bool: - """Check whether an ast.Attribute is an attrs attribute or not.""" - s1 = f"attr.{getattr(attribute, 'attr', '')}" - s2 = f"attrs.{getattr(attribute, 'attrs', '')}" - actual = [s1, s2] - return any(e for e in actual if e in ATTRS_DECORATORS) - - @staticmethod - def is_attrs_str(attribute: str | ast.expr, attrs_imports: dict[str | None, str]) -> bool: - """Check whether an ast.expr or string is an attrs string or not.""" - actual = attrs_imports.get(str(attribute), '') - return actual in ATTRS_DECORATORS + decorator = decorator.func + return self.lookup_full_name(decorator) in ATTRS_DECORATORS class DunderAllMixin: diff --git a/flake8_type_checking/constants.py b/flake8_type_checking/constants.py index fc9410c..8691fd4 100644 --- a/flake8_type_checking/constants.py +++ b/flake8_type_checking/constants.py @@ -16,7 +16,6 @@ 'attr.mutable', 'attr.s', ] -ATTRS_IMPORTS = {'attrs', 'attr'} flake_version_gt_v4 = tuple(int(i) for i in flake8.__version__.split('.')) >= (4, 0, 0) diff --git a/flake8_type_checking/types.py b/flake8_type_checking/types.py index c83805b..dde25c6 100644 --- a/flake8_type_checking/types.py +++ b/flake8_type_checking/types.py @@ -5,17 +5,13 @@ if TYPE_CHECKING: import ast from collections.abc import Generator - from typing import Any, Optional, Protocol, Union + from typing import Any, Protocol, Union Function = Union[ast.FunctionDef, ast.AsyncFunctionDef, ast.Lambda] Comprehension = Union[ast.ListComp, ast.SetComp, ast.DictComp, ast.GeneratorExp] Import = Union[ast.Import, ast.ImportFrom] Flake8Generator = Generator[tuple[int, int, str, Any], None, None] - class Name(Protocol): - asname: Optional[str] - name: str - class HasPosition(Protocol): @property def lineno(self) -> int: