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 64 65 66 67 68 69 70 71 72 73 74
|
from dataclasses import dataclass
from mypy.nodes import BytesExpr, CallExpr, NameExpr, RefExpr, StrExpr, Var
from refurb.checks.common import normalize_os_path
from refurb.checks.pathlib.util import is_pathlike
from refurb.error import Error
@dataclass
class ErrorInfo(Error):
"""
Don't use the `os.path.getsize` (or similar) functions, use the more modern
`pathlib` module instead:
Bad:
```
if os.path.getsize("file.txt"):
pass
```
Good:
```
if Path("file.txt").stat().st_size:
pass
```
"""
name = "use-pathlib-stat"
code = 155
categories = ("pathlib",)
PATH_TO_PATHLIB_NAMES = {
"os.stat": "stat()",
"os.path.getsize": "stat().st_size",
"os.path.getatime": "stat().st_atime",
"os.path.getmtime": "stat().st_mtime",
"os.path.getctime": "stat().st_ctime",
}
def check(node: CallExpr, errors: list[Error]) -> None:
match node:
case CallExpr(callee=RefExpr(fullname=fullname), args=[arg]):
normalized_name = normalize_os_path(fullname)
new_name = PATH_TO_PATHLIB_NAMES.get(normalized_name)
if not new_name:
return
if is_pathlike(arg):
replace = f"x.{new_name}"
else:
match arg:
case BytesExpr() | StrExpr():
pass
case NameExpr(node=Var(type=ty)) if (
str(ty) in {"builtins.str", "builtins.bytes"}
):
pass
case _:
return
replace = f"Path(x).{new_name}"
errors.append(
ErrorInfo.from_node(node, f"Replace `{normalized_name}(x)` with `{replace}`")
)
|