Skip to content

Commit

Permalink
refactor: Simplifies attrs support
Browse files Browse the repository at this point in the history
  • Loading branch information
Daverball authored Jan 20, 2025
1 parent 04d1a05 commit 7d24f79
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 48 deletions.
48 changes: 6 additions & 42 deletions flake8_type_checking/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
ANNOTATION_PROPERTY,
ATTRIBUTE_PROPERTY,
ATTRS_DECORATORS,
ATTRS_IMPORTS,
BINOP_OPERAND_PROPERTY,
MISSING,
TC001,
Expand Down Expand Up @@ -53,7 +52,6 @@
HasPosition,
Import,
ImportTypeValue,
Name,
SupportsIsTyping,
)

Expand Down Expand Up @@ -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:
Expand Down
1 change: 0 additions & 1 deletion flake8_type_checking/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
6 changes: 1 addition & 5 deletions flake8_type_checking/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down

0 comments on commit 7d24f79

Please sign in to comment.