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 61 62 63
|
from dataclasses import dataclass
from mypy.nodes import ArgKind, CallExpr, Decorator, MemberExpr, NameExpr, RefExpr
from refurb.error import Error
from refurb.settings import Settings
@dataclass
class ErrorInfo(Error):
"""
Python 3.9 introduces the `@cache` decorator which can be used as a
short-hand for `@lru_cache(maxsize=None)`.
Bad:
```
from functools import lru_cache
@lru_cache(maxsize=None)
def f(x: int) -> int:
return x + 1
```
Good:
```
from functools import cache
@cache
def f(x: int) -> int:
return x + 1
```
"""
name = "use-cache"
code = 134
msg: str = "Replace `@lru_cache(maxsize=None)` with `@cache`"
categories = ("functools", "python39", "readability")
def check(node: Decorator, errors: list[Error], settings: Settings) -> None:
if settings.get_python_version() < (3, 9):
return # pragma: no cover
match node:
case Decorator(
decorators=[
CallExpr(
callee=RefExpr(fullname="functools.lru_cache") as ref,
arg_names=["maxsize"],
arg_kinds=[ArgKind.ARG_NAMED],
args=[NameExpr(fullname="builtins.None")],
)
]
):
prefix = "functools." if isinstance(ref, MemberExpr) else ""
old = f"@{prefix}lru_cache(maxsize=None)"
new = f"@{prefix}cache"
msg = f"Replace `{old}` with `{new}`"
errors.append(ErrorInfo.from_node(node, msg))
|