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 75
|
from dataclasses import dataclass
from typing import cast
from mypy.nodes import CallExpr, RefExpr
from refurb.error import Error
from .util import is_pathlike
@dataclass
class ErrorInfo(Error):
"""
Use the `mkdir` method from the pathlib library instead of using the
`mkdir` and `makedirs` functions from the `os` library: the pathlib library
is more modern and provides better flexibility over the construction and
manipulation of file paths.
Bad:
```
import os
os.mkdir("new_folder")
```
Good:
```
from pathlib import Path
Path("new_folder").mkdir()
```
"""
name = "use-pathlib-mkdir"
code = 150
categories = ("pathlib",)
def create_error(node: CallExpr) -> list[Error]:
old_args = ["x"]
new_args = []
fullname = cast(RefExpr, node.callee).fullname
is_makedirs = fullname == "os.makedirs"
allowed_names = [None, "mode"]
if is_makedirs:
allowed_names.append("exist_ok")
if len(node.args) > 1:
if any(name not in allowed_names for name in node.arg_names):
return []
old_args.append("...")
new_args.append("...")
if is_makedirs:
new_args.append("parents=True")
new_args = ", ".join(new_args)
expr = f"x.mkdir({new_args})" if is_pathlike(node.args[0]) else f"Path(x).mkdir({new_args})"
return [
ErrorInfo.from_node(node, f"Replace `{fullname}({', '.join(old_args)})` with `{expr}`")
]
def check(node: CallExpr, errors: list[Error]) -> None:
match node:
case CallExpr(callee=RefExpr(fullname="os.mkdir" | "os.makedirs"), args=args) if args:
errors.extend(create_error(node))
|