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
|
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.isfile` (or similar) functions, use the more modern
`pathlib` module instead:
Bad:
```
if os.path.isfile("file.txt"):
pass
```
Good:
```
if Path("file.txt").is_file():
pass
```
"""
name = "use-pathlib-is-funcs"
code = 146
categories = ("pathlib",)
PATH_TO_PATHLIB_NAMES = {
"os.path.isabs": "is_absolute",
"os.path.isdir": "is_dir",
"os.path.isfile": "is_file",
"os.path.islink": "is_symlink",
}
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}`")
)
|