1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
from dataclasses import dataclass
from mypy.nodes import CallExpr, Decorator, FuncDef, MemberExpr, NameExpr, TypeInfo
from refurb.error import Error
@dataclass
class ErrorInfo(Error):
"""
You don't need to construct a class object to call a static method or a
class method, just invoke the method on the class directly:
Bad:
```
cwd = Path().cwd()
```
Good:
```
cwd = Path.cwd()
```
"""
name = "no-temp-class-object"
code = 165
categories = ("readability",)
def check(node: CallExpr, errors: list[Error]) -> None:
match node:
case CallExpr(
callee=MemberExpr(
expr=CallExpr(
callee=NameExpr(node=TypeInfo() as klass),
args=class_args,
),
name=func_name,
),
args=func_args,
):
for func in klass.defn.defs.body:
if isinstance(func, Decorator):
func = func.func # noqa: PLW2901
elif not isinstance(func, FuncDef):
continue
if func.name == func_name and (func.is_class or func.is_static):
class_name = klass.defn.name
class_args = "..." if class_args else "" # type: ignore
func_args = "..." if func_args else "" # type: ignore
old = f"{class_name}({class_args}).{func_name}({func_args})" # noqa: E501
new = f"{class_name}.{func_name}({func_args})"
errors.append(ErrorInfo.from_node(node, f"Replace `{old}` with `{new}`"))
|