diff --git a/README.md b/README.md index 7d2093536aaa6..2c14399a83584 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ developer of [Zulip](https://github.com/zulip/zulip): 1. [flake8-executable (EXE)](#flake8-executable-exe) 1. [flake8-type-checking (TYP)](#flake8-type-checking-typ) 1. [tryceratops (TRY)](#tryceratops-try) + 1. [flake8-use-pathlib (PTH)](#flake8-use-pathlib-pth) 1. [Ruff-specific rules (RUF)](#ruff-specific-rules-ruf) 1. [Editor Integrations](#editor-integrations) 1. [FAQ](#faq) @@ -1197,6 +1198,38 @@ For more, see [tryceratops](https://pypi.org/project/tryceratops/1.1.0/) on PyPI | TRY004 | prefer-type-error | Prefer `TypeError` exception for invalid type | 🛠 | | TRY300 | try-consider-else | Consider `else` block | | +### flake8-use-pathlib (PTH) + +For more, see [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/) on PyPI. + +| Code | Name | Message | Fix | +| ---- | ---- | ------- | --- | +| PTH100 | pathlib-abspath | `os.path.abspath` should be replaced by `.resolve()` | | +| PTH101 | pathlib-chmod | `os.chmod` should be replaced by `.chmod()` | | +| PTH102 | pathlib-mkdir | `os.mkdir` should be replaced by `.mkdir()` | | +| PTH103 | pathlib-makedirs | `os.makedirs` should be replaced by `.mkdir(parents=True)` | | +| PTH104 | pathlib-rename | `os.rename` should be replaced by `.rename()` | | +| PTH105 | pathlib-replace | `os.replace`should be replaced by `.replace()` | | +| PTH106 | pathlib-rmdir | `os.rmdir` should be replaced by `.rmdir()` | | +| PTH107 | pathlib-remove | `os.remove` should be replaced by `.unlink()` | | +| PTH108 | pathlib-unlink | `os.unlink` should be replaced by `.unlink()` | | +| PTH109 | pathlib-getcwd | `os.getcwd()` should be replaced by `Path.cwd()` | | +| PTH110 | pathlib-exists | `os.path.exists` should be replaced by `.exists()` | | +| PTH111 | pathlib-expanduser | `os.path.expanduser` should be replaced by `.expanduser()` | | +| PTH112 | pathlib-is-dir | `os.path.isdir` should be replaced by `.is_dir()` | | +| PTH113 | pathlib-is-file | `os.path.isfile` should be replaced by `.is_file()` | | +| PTH114 | pathlib-is-link | `os.path.islink` should be replaced by `.is_symlink()` | | +| PTH115 | pathlib-readlink | `os.readlink(` should be replaced by `.readlink()` | | +| PTH116 | pathlib-stat | `os.stat` should be replaced by `.stat()` or `.owner()` or `.group()` | | +| PTH117 | pathlib-is-abs | `os.path.isabs` should be replaced by `.is_absolute()` | | +| PTH118 | pathlib-join | `os.path.join` should be replaced by foo_path / "bar" | | +| PTH119 | pathlib-basename | `os.path.basename` should be replaced by `.name` | | +| PTH120 | pathlib-dirname | `os.path.dirname` should be replaced by `.parent` | | +| PTH121 | pathlib-samefile | `os.path.samefile` should be replaced by `.samefile()` | | +| PTH122 | pathlib-splitext | `os.path.splitext` should be replaced by `.suffix` | | +| PTH123 | pathlib-open | `open("foo")` should be replaced by`Path("foo").open()` | | +| PTH124 | pathlib-py-path | `py.path` is in maintenance mode, use `pathlib` instead | | + ### Ruff-specific rules (RUF) | Code | Name | Message | Fix | diff --git a/licenses/LICENSE_RoPP_flake8-use-pathlib b/licenses/LICENSE_RoPP_flake8-use-pathlib new file mode 100644 index 0000000000000..d0acd6e7cb6f7 --- /dev/null +++ b/licenses/LICENSE_RoPP_flake8-use-pathlib @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2021 Rodolphe Pelloux-Prayer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/resources/test/fixtures/flake8_use_pathlib/full_name.py b/resources/test/fixtures/flake8_use_pathlib/full_name.py new file mode 100644 index 0000000000000..6d6ec8ed1d0ac --- /dev/null +++ b/resources/test/fixtures/flake8_use_pathlib/full_name.py @@ -0,0 +1,31 @@ +import os +import os.path + +p = "/foo" + +a = os.path.abspath(p) +aa = os.chmod(p) +aaa = os.mkdir(p) +os.makedirs(p) +os.rename(p) +os.replace(p) +os.rmdir(p) +os.remove(p) +os.unlink(p) +os.getcwd(p) +b = os.path.exists(p) +bb = os.path.expanduser(p) +bbb = os.path.isdir(p) +bbbb = os.path.isfile(p) +bbbbb = os.path.islink(p) +os.readlink(p) +os.stat(p) +os.path.isabs(p) +os.path.join(p) +os.path.basename(p) +os.path.dirname(p) +os.path.samefile(p) +os.path.splitext(p) +with open(p) as fp: + fp.read() +open(p).close() diff --git a/resources/test/fixtures/flake8_use_pathlib/import_as.py b/resources/test/fixtures/flake8_use_pathlib/import_as.py new file mode 100644 index 0000000000000..446412f18de67 --- /dev/null +++ b/resources/test/fixtures/flake8_use_pathlib/import_as.py @@ -0,0 +1,28 @@ +import os as foo +import os.path as foo_p + +p = "/foo" + +a = foo_p.abspath(p) +aa = foo.chmod(p) +aaa = foo.mkdir(p) +foo.makedirs(p) +foo.rename(p) +foo.replace(p) +foo.rmdir(p) +foo.remove(p) +foo.unlink(p) +foo.getcwd(p) +b = foo_p.exists(p) +bb = foo_p.expanduser(p) +bbb = foo_p.isdir(p) +bbbb = foo_p.isfile(p) +bbbbb = foo_p.islink(p) +foo.readlink(p) +foo.stat(p) +foo_p.isabs(p) +foo_p.join(p) +foo_p.basename(p) +foo_p.dirname(p) +foo_p.samefile(p) +foo_p.splitext(p) diff --git a/resources/test/fixtures/flake8_use_pathlib/import_from.py b/resources/test/fixtures/flake8_use_pathlib/import_from.py new file mode 100644 index 0000000000000..9e4dc71a2d647 --- /dev/null +++ b/resources/test/fixtures/flake8_use_pathlib/import_from.py @@ -0,0 +1,33 @@ +from os import chmod, mkdir, makedirs, rename, replace, rmdir +from os import remove, unlink, getcwd, readlink, stat +from os.path import abspath, exists, expanduser, isdir, isfile, islink +from os.path import isabs, join, basename, dirname, samefile, splitext + +p = "/foo" + +a = abspath(p) +aa = chmod(p) +aaa = mkdir(p) +makedirs(p) +rename(p) +replace(p) +rmdir(p) +remove(p) +unlink(p) +getcwd(p) +b = exists(p) +bb = expanduser(p) +bbb = isdir(p) +bbbb = isfile(p) +bbbbb = islink(p) +readlink(p) +stat(p) +isabs(p) +join(p) +basename(p) +dirname(p) +samefile(p) +splitext(p) +with open(p) as fp: + fp.read() +open(p).close() diff --git a/resources/test/fixtures/flake8_use_pathlib/import_from_as.py b/resources/test/fixtures/flake8_use_pathlib/import_from_as.py new file mode 100644 index 0000000000000..2beff6d7e7bb5 --- /dev/null +++ b/resources/test/fixtures/flake8_use_pathlib/import_from_as.py @@ -0,0 +1,35 @@ +from os import chmod as xchmod, mkdir as xmkdir +from os import makedirs as xmakedirs, rename as xrename, replace as xreplace +from os import rmdir as xrmdir, remove as xremove, unlink as xunlink +from os import getcwd as xgetcwd, readlink as xreadlink, stat as xstat +from os.path import abspath as xabspath, exists as xexists +from os.path import expanduser as xexpanduser, isdir as xisdir +from os.path import isfile as xisfile, islink as xislink, isabs as xisabs +from os.path import join as xjoin, basename as xbasename, dirname as xdirname +from os.path import samefile as xsamefile, splitext as xsplitext + +p = "/foo" + +a = xabspath(p) +aa = xchmod(p) +aaa = xmkdir(p) +xmakedirs(p) +xrename(p) +xreplace(p) +xrmdir(p) +xremove(p) +xunlink(p) +xgetcwd(p) +b = xexists(p) +bb = xexpanduser(p) +bbb = xisdir(p) +bbbb = xisfile(p) +bbbbb = xislink(p) +xreadlink(p) +xstat(p) +xisabs(p) +xjoin(p) +xbasename(p) +xdirname(p) +xsamefile(p) +xsplitext(p) diff --git a/resources/test/fixtures/flake8_use_pathlib/py_path_1.py b/resources/test/fixtures/flake8_use_pathlib/py_path_1.py new file mode 100644 index 0000000000000..27c6205c81350 --- /dev/null +++ b/resources/test/fixtures/flake8_use_pathlib/py_path_1.py @@ -0,0 +1,3 @@ +import py + +p = py.path.local("../foo") diff --git a/resources/test/fixtures/flake8_use_pathlib/py_path_2.py b/resources/test/fixtures/flake8_use_pathlib/py_path_2.py new file mode 100644 index 0000000000000..fc25529fb2e90 --- /dev/null +++ b/resources/test/fixtures/flake8_use_pathlib/py_path_2.py @@ -0,0 +1,3 @@ +from py.path import local as path + +p = path("/foo") diff --git a/ruff.schema.json b/ruff.schema.json index 1883aa5b75e20..792a4096ad8ad 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -1633,6 +1633,36 @@ "PT024", "PT025", "PT026", + "PTH", + "PTH1", + "PTH10", + "PTH100", + "PTH101", + "PTH102", + "PTH103", + "PTH104", + "PTH105", + "PTH106", + "PTH107", + "PTH108", + "PTH109", + "PTH11", + "PTH110", + "PTH111", + "PTH112", + "PTH113", + "PTH114", + "PTH115", + "PTH116", + "PTH117", + "PTH118", + "PTH119", + "PTH12", + "PTH120", + "PTH121", + "PTH122", + "PTH123", + "PTH124", "Q", "Q0", "Q00", diff --git a/scripts/add_rule.py b/scripts/add_rule.py index d80a8b58bc1a4..2e08bbc4df70e 100755 --- a/scripts/add_rule.py +++ b/scripts/add_rule.py @@ -116,7 +116,7 @@ def main(*, name: str, code: str, linter: str) -> None: if line.strip() == f"// {linter}": indent = get_indent(line) - fp.write(f"{indent}{code} => rules::{linter}::rules::{name},") + fp.write(f"{indent}{code} => rules::{dir_name(linter)}::rules::{name},") fp.write("\n") has_written = True diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index dcd40a2901a8a..94c5045e948ae 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -36,8 +36,8 @@ use crate::rules::{ flake8_bugbear, flake8_builtins, flake8_comprehensions, flake8_datetimez, flake8_debugger, flake8_errmsg, flake8_implicit_str_concat, flake8_import_conventions, flake8_pie, flake8_print, flake8_pytest_style, flake8_return, flake8_simplify, flake8_tidy_imports, flake8_type_checking, - flake8_unused_arguments, mccabe, pandas_vet, pep8_naming, pycodestyle, pydocstyle, pyflakes, - pygrep_hooks, pylint, pyupgrade, ruff, tryceratops, + flake8_unused_arguments, flake8_use_pathlib, mccabe, pandas_vet, pep8_naming, pycodestyle, + pydocstyle, pyflakes, pygrep_hooks, pylint, pyupgrade, ruff, tryceratops, }; use crate::settings::types::PythonVersion; use crate::settings::{flags, Settings}; @@ -2545,6 +2545,35 @@ where { flake8_simplify::rules::open_file_with_context_handler(self, func); } + + // flake8-use-pathlib + if self.settings.rules.enabled(&Rule::PathlibAbspath) + || self.settings.rules.enabled(&Rule::PathlibChmod) + || self.settings.rules.enabled(&Rule::PathlibMkdir) + || self.settings.rules.enabled(&Rule::PathlibMakedirs) + || self.settings.rules.enabled(&Rule::PathlibRename) + || self.settings.rules.enabled(&Rule::PathlibReplace) + || self.settings.rules.enabled(&Rule::PathlibRmdir) + || self.settings.rules.enabled(&Rule::PathlibRemove) + || self.settings.rules.enabled(&Rule::PathlibUnlink) + || self.settings.rules.enabled(&Rule::PathlibGetcwd) + || self.settings.rules.enabled(&Rule::PathlibExists) + || self.settings.rules.enabled(&Rule::PathlibExpanduser) + || self.settings.rules.enabled(&Rule::PathlibIsDir) + || self.settings.rules.enabled(&Rule::PathlibIsFile) + || self.settings.rules.enabled(&Rule::PathlibIsLink) + || self.settings.rules.enabled(&Rule::PathlibReadlink) + || self.settings.rules.enabled(&Rule::PathlibStat) + || self.settings.rules.enabled(&Rule::PathlibIsAbs) + || self.settings.rules.enabled(&Rule::PathlibJoin) + || self.settings.rules.enabled(&Rule::PathlibBasename) + || self.settings.rules.enabled(&Rule::PathlibSamefile) + || self.settings.rules.enabled(&Rule::PathlibSplitext) + || self.settings.rules.enabled(&Rule::PathlibOpen) + || self.settings.rules.enabled(&Rule::PathlibPyPath) + { + flake8_use_pathlib::helpers::replaceable_by_pathlib(self, func); + } } ExprKind::Dict { keys, values } => { if self diff --git a/src/registry.rs b/src/registry.rs index cc76d4c502f70..4d66462b28341 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -429,6 +429,32 @@ ruff_macros::define_rule_mapping!( // tryceratops TRY004 => rules::tryceratops::rules::PreferTypeError, TRY300 => rules::tryceratops::rules::TryConsiderElse, + // flake8-use-pathlib + PTH100 => rules::flake8_use_pathlib::violations::PathlibAbspath, + PTH101 => rules::flake8_use_pathlib::violations::PathlibChmod, + PTH102 => rules::flake8_use_pathlib::violations::PathlibMkdir, + PTH103 => rules::flake8_use_pathlib::violations::PathlibMakedirs, + PTH104 => rules::flake8_use_pathlib::violations::PathlibRename, + PTH105 => rules::flake8_use_pathlib::violations::PathlibReplace, + PTH106 => rules::flake8_use_pathlib::violations::PathlibRmdir, + PTH107 => rules::flake8_use_pathlib::violations::PathlibRemove, + PTH108 => rules::flake8_use_pathlib::violations::PathlibUnlink, + PTH109 => rules::flake8_use_pathlib::violations::PathlibGetcwd, + PTH110 => rules::flake8_use_pathlib::violations::PathlibExists, + PTH111 => rules::flake8_use_pathlib::violations::PathlibExpanduser, + PTH112 => rules::flake8_use_pathlib::violations::PathlibIsDir, + PTH113 => rules::flake8_use_pathlib::violations::PathlibIsFile, + PTH114 => rules::flake8_use_pathlib::violations::PathlibIsLink, + PTH115 => rules::flake8_use_pathlib::violations::PathlibReadlink, + PTH116 => rules::flake8_use_pathlib::violations::PathlibStat, + PTH117 => rules::flake8_use_pathlib::violations::PathlibIsAbs, + PTH118 => rules::flake8_use_pathlib::violations::PathlibJoin, + PTH119 => rules::flake8_use_pathlib::violations::PathlibBasename, + PTH120 => rules::flake8_use_pathlib::violations::PathlibDirname, + PTH121 => rules::flake8_use_pathlib::violations::PathlibSamefile, + PTH122 => rules::flake8_use_pathlib::violations::PathlibSplitext, + PTH123 => rules::flake8_use_pathlib::violations::PathlibOpen, + PTH124 => rules::flake8_use_pathlib::violations::PathlibPyPath, // ruff RUF001 => violations::AmbiguousUnicodeCharacterString, RUF002 => violations::AmbiguousUnicodeCharacterDocstring, @@ -515,6 +541,8 @@ pub enum Linter { Flake8TypeChecking, #[prefix = "TRY"] Tryceratops, + #[prefix = "PTH"] + Flake8UsePathlib, #[prefix = "RUF"] Ruff, } diff --git a/src/rules/flake8_use_pathlib/helpers.rs b/src/rules/flake8_use_pathlib/helpers.rs new file mode 100644 index 0000000000000..053d51fe13d4a --- /dev/null +++ b/src/rules/flake8_use_pathlib/helpers.rs @@ -0,0 +1,110 @@ +use rustpython_ast::Expr; + +use crate::ast::types::Range; +use crate::checkers::ast::Checker; +use crate::registry::{Diagnostic, DiagnosticKind}; +use crate::rules::flake8_use_pathlib::violations::{ + PathlibAbspath, PathlibBasename, PathlibChmod, PathlibDirname, PathlibExists, + PathlibExpanduser, PathlibGetcwd, PathlibIsAbs, PathlibIsDir, PathlibIsFile, PathlibIsLink, + PathlibJoin, PathlibMakedirs, PathlibMkdir, PathlibOpen, PathlibPyPath, PathlibReadlink, + PathlibRemove, PathlibRename, PathlibReplace, PathlibRmdir, PathlibSamefile, PathlibSplitext, + PathlibStat, PathlibUnlink, +}; + +enum OsCall { + Abspath, + Chmod, + Mkdir, + Makedirs, + Rename, + Replace, + Rmdir, + Remove, + Unlink, + Getcwd, + Exists, + Expanduser, + IsDir, + IsFile, + IsLink, + Readlink, + Stat, + IsAbs, + Join, + Basename, + Dirname, + Samefile, + Splitext, + Open, + PyPath, +} + +pub fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) { + if let Some(os_call) = + checker + .resolve_call_path(expr) + .and_then(|call_path| match call_path.as_slice() { + ["os", "path", "abspath"] => Some(OsCall::Abspath), + ["os", "chmod"] => Some(OsCall::Chmod), + ["os", "mkdir"] => Some(OsCall::Mkdir), + ["os", "makedirs"] => Some(OsCall::Makedirs), + ["os", "rename"] => Some(OsCall::Rename), + ["os", "replace"] => Some(OsCall::Replace), + ["os", "rmdir"] => Some(OsCall::Rmdir), + ["os", "remove"] => Some(OsCall::Remove), + ["os", "unlink"] => Some(OsCall::Unlink), + ["os", "getcwd"] => Some(OsCall::Getcwd), + ["os", "path", "exists"] => Some(OsCall::Exists), + ["os", "path", "expanduser"] => Some(OsCall::Expanduser), + ["os", "path", "isdir"] => Some(OsCall::IsDir), + ["os", "path", "isfile"] => Some(OsCall::IsFile), + ["os", "path", "islink"] => Some(OsCall::IsLink), + ["os", "readlink"] => Some(OsCall::Readlink), + ["os", "stat"] => Some(OsCall::Stat), + ["os", "path", "isabs"] => Some(OsCall::IsAbs), + ["os", "path", "join"] => Some(OsCall::Join), + ["os", "path", "basename"] => Some(OsCall::Basename), + ["os", "path", "dirname"] => Some(OsCall::Dirname), + ["os", "path", "samefile"] => Some(OsCall::Samefile), + ["os", "path", "splitext"] => Some(OsCall::Splitext), + ["", "open"] => Some(OsCall::Open), + ["py", "path", "local"] => Some(OsCall::PyPath), + _ => None, + }) + { + let diagnostic = Diagnostic::new::( + match os_call { + OsCall::Abspath => PathlibAbspath.into(), + OsCall::Chmod => PathlibChmod.into(), + OsCall::Mkdir => PathlibMkdir.into(), + OsCall::Makedirs => PathlibMakedirs.into(), + OsCall::Rename => PathlibRename.into(), + OsCall::Replace => PathlibReplace.into(), + OsCall::Rmdir => PathlibRmdir.into(), + OsCall::Remove => PathlibRemove.into(), + OsCall::Unlink => PathlibUnlink.into(), + OsCall::Getcwd => PathlibGetcwd.into(), + OsCall::Exists => PathlibExists.into(), + OsCall::Expanduser => PathlibExpanduser.into(), + OsCall::IsDir => PathlibIsDir.into(), + OsCall::IsFile => PathlibIsFile.into(), + OsCall::IsLink => PathlibIsLink.into(), + OsCall::Readlink => PathlibReadlink.into(), + OsCall::Stat => PathlibStat.into(), + OsCall::IsAbs => PathlibIsAbs.into(), + OsCall::Join => PathlibJoin.into(), + OsCall::Basename => PathlibBasename.into(), + OsCall::Dirname => PathlibDirname.into(), + OsCall::Samefile => PathlibSamefile.into(), + OsCall::Splitext => PathlibSplitext.into(), + OsCall::Open => PathlibOpen.into(), + OsCall::PyPath => PathlibPyPath.into(), + }, + Range::from_located(expr), + ); + + if checker.settings.rules.enabled(diagnostic.kind.rule()) { + checker.diagnostics.push(diagnostic); + } + } +} diff --git a/src/rules/flake8_use_pathlib/mod.rs b/src/rules/flake8_use_pathlib/mod.rs new file mode 100644 index 0000000000000..27944b701469d --- /dev/null +++ b/src/rules/flake8_use_pathlib/mod.rs @@ -0,0 +1,70 @@ +//! Rules from [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/). +pub(crate) mod helpers; +pub(crate) mod violations; + +#[cfg(test)] +mod tests { + use std::path::Path; + + use anyhow::Result; + use test_case::test_case; + + use crate::linter::test_path; + use crate::registry::Rule; + use crate::settings; + + #[test_case(Path::new("full_name.py"); "PTH1_1")] + #[test_case(Path::new("import_as.py"); "PTH1_2")] + #[test_case(Path::new("import_from_as.py"); "PTH1_3")] + #[test_case(Path::new("import_from.py"); "PTH1_4")] + fn rules(path: &Path) -> Result<()> { + let snapshot = format!("{}", path.to_string_lossy()); + let diagnostics = test_path( + Path::new("./resources/test/fixtures/flake8_use_pathlib") + .join(path) + .as_path(), + &settings::Settings::for_rules(vec![ + Rule::PathlibAbspath, + Rule::PathlibChmod, + Rule::PathlibMkdir, + Rule::PathlibMakedirs, + Rule::PathlibRename, + Rule::PathlibReplace, + Rule::PathlibRmdir, + Rule::PathlibRemove, + Rule::PathlibUnlink, + Rule::PathlibGetcwd, + Rule::PathlibExists, + Rule::PathlibExpanduser, + Rule::PathlibIsDir, + Rule::PathlibIsFile, + Rule::PathlibIsLink, + Rule::PathlibReadlink, + Rule::PathlibStat, + Rule::PathlibIsAbs, + Rule::PathlibJoin, + Rule::PathlibBasename, + Rule::PathlibDirname, + Rule::PathlibSamefile, + Rule::PathlibSplitext, + Rule::PathlibOpen, + ]), + )?; + insta::assert_yaml_snapshot!(snapshot, diagnostics); + Ok(()) + } + + #[test_case(Rule::PathlibPyPath, Path::new("py_path_1.py"); "PTH024_1")] + #[test_case(Rule::PathlibPyPath, Path::new("py_path_2.py"); "PTH024_2")] + fn rules_pypath(rule_code: Rule, path: &Path) -> Result<()> { + let snapshot = format!("{}_{}", rule_code.code(), path.to_string_lossy()); + let diagnostics = test_path( + Path::new("./resources/test/fixtures/flake8_use_pathlib") + .join(path) + .as_path(), + &settings::Settings::for_rule(rule_code), + )?; + insta::assert_yaml_snapshot!(snapshot, diagnostics); + Ok(()) + } +} diff --git a/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__PTH124_py_path_1.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__PTH124_py_path_1.py.snap new file mode 100644 index 0000000000000..b27363952472b --- /dev/null +++ b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__PTH124_py_path_1.py.snap @@ -0,0 +1,15 @@ +--- +source: src/rules/flake8_use_pathlib/mod.rs +expression: diagnostics +--- +- kind: + PathlibPyPath: ~ + location: + row: 3 + column: 4 + end_location: + row: 3 + column: 17 + fix: ~ + parent: ~ + diff --git a/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__PTH124_py_path_2.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__PTH124_py_path_2.py.snap new file mode 100644 index 0000000000000..c5f6ad5501c67 --- /dev/null +++ b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__PTH124_py_path_2.py.snap @@ -0,0 +1,15 @@ +--- +source: src/rules/flake8_use_pathlib/mod.rs +expression: diagnostics +--- +- kind: + PathlibPyPath: ~ + location: + row: 3 + column: 4 + end_location: + row: 3 + column: 8 + fix: ~ + parent: ~ + diff --git a/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__full_name.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__full_name.py.snap new file mode 100644 index 0000000000000..d14875f4966b5 --- /dev/null +++ b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__full_name.py.snap @@ -0,0 +1,255 @@ +--- +source: src/rules/flake8_use_pathlib/mod.rs +expression: diagnostics +--- +- kind: + PathlibAbspath: ~ + location: + row: 6 + column: 4 + end_location: + row: 6 + column: 19 + fix: ~ + parent: ~ +- kind: + PathlibChmod: ~ + location: + row: 7 + column: 5 + end_location: + row: 7 + column: 13 + fix: ~ + parent: ~ +- kind: + PathlibMkdir: ~ + location: + row: 8 + column: 6 + end_location: + row: 8 + column: 14 + fix: ~ + parent: ~ +- kind: + PathlibMakedirs: ~ + location: + row: 9 + column: 0 + end_location: + row: 9 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibRename: ~ + location: + row: 10 + column: 0 + end_location: + row: 10 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibReplace: ~ + location: + row: 11 + column: 0 + end_location: + row: 11 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibRmdir: ~ + location: + row: 12 + column: 0 + end_location: + row: 12 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibRemove: ~ + location: + row: 13 + column: 0 + end_location: + row: 13 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibUnlink: ~ + location: + row: 14 + column: 0 + end_location: + row: 14 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibGetcwd: ~ + location: + row: 15 + column: 0 + end_location: + row: 15 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibExists: ~ + location: + row: 16 + column: 4 + end_location: + row: 16 + column: 18 + fix: ~ + parent: ~ +- kind: + PathlibExpanduser: ~ + location: + row: 17 + column: 5 + end_location: + row: 17 + column: 23 + fix: ~ + parent: ~ +- kind: + PathlibIsDir: ~ + location: + row: 18 + column: 6 + end_location: + row: 18 + column: 19 + fix: ~ + parent: ~ +- kind: + PathlibIsFile: ~ + location: + row: 19 + column: 7 + end_location: + row: 19 + column: 21 + fix: ~ + parent: ~ +- kind: + PathlibIsLink: ~ + location: + row: 20 + column: 8 + end_location: + row: 20 + column: 22 + fix: ~ + parent: ~ +- kind: + PathlibReadlink: ~ + location: + row: 21 + column: 0 + end_location: + row: 21 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibStat: ~ + location: + row: 22 + column: 0 + end_location: + row: 22 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibIsAbs: ~ + location: + row: 23 + column: 0 + end_location: + row: 23 + column: 13 + fix: ~ + parent: ~ +- kind: + PathlibJoin: ~ + location: + row: 24 + column: 0 + end_location: + row: 24 + column: 12 + fix: ~ + parent: ~ +- kind: + PathlibBasename: ~ + location: + row: 25 + column: 0 + end_location: + row: 25 + column: 16 + fix: ~ + parent: ~ +- kind: + PathlibDirname: ~ + location: + row: 26 + column: 0 + end_location: + row: 26 + column: 15 + fix: ~ + parent: ~ +- kind: + PathlibSamefile: ~ + location: + row: 27 + column: 0 + end_location: + row: 27 + column: 16 + fix: ~ + parent: ~ +- kind: + PathlibSplitext: ~ + location: + row: 28 + column: 0 + end_location: + row: 28 + column: 16 + fix: ~ + parent: ~ +- kind: + PathlibOpen: ~ + location: + row: 29 + column: 5 + end_location: + row: 29 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibOpen: ~ + location: + row: 31 + column: 0 + end_location: + row: 31 + column: 4 + fix: ~ + parent: ~ + diff --git a/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_as.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_as.py.snap new file mode 100644 index 0000000000000..956e8e62b6b9f --- /dev/null +++ b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_as.py.snap @@ -0,0 +1,235 @@ +--- +source: src/rules/flake8_use_pathlib/mod.rs +expression: diagnostics +--- +- kind: + PathlibAbspath: ~ + location: + row: 6 + column: 4 + end_location: + row: 6 + column: 17 + fix: ~ + parent: ~ +- kind: + PathlibChmod: ~ + location: + row: 7 + column: 5 + end_location: + row: 7 + column: 14 + fix: ~ + parent: ~ +- kind: + PathlibMkdir: ~ + location: + row: 8 + column: 6 + end_location: + row: 8 + column: 15 + fix: ~ + parent: ~ +- kind: + PathlibMakedirs: ~ + location: + row: 9 + column: 0 + end_location: + row: 9 + column: 12 + fix: ~ + parent: ~ +- kind: + PathlibRename: ~ + location: + row: 10 + column: 0 + end_location: + row: 10 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibReplace: ~ + location: + row: 11 + column: 0 + end_location: + row: 11 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibRmdir: ~ + location: + row: 12 + column: 0 + end_location: + row: 12 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibRemove: ~ + location: + row: 13 + column: 0 + end_location: + row: 13 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibUnlink: ~ + location: + row: 14 + column: 0 + end_location: + row: 14 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibGetcwd: ~ + location: + row: 15 + column: 0 + end_location: + row: 15 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibExists: ~ + location: + row: 16 + column: 4 + end_location: + row: 16 + column: 16 + fix: ~ + parent: ~ +- kind: + PathlibExpanduser: ~ + location: + row: 17 + column: 5 + end_location: + row: 17 + column: 21 + fix: ~ + parent: ~ +- kind: + PathlibIsDir: ~ + location: + row: 18 + column: 6 + end_location: + row: 18 + column: 17 + fix: ~ + parent: ~ +- kind: + PathlibIsFile: ~ + location: + row: 19 + column: 7 + end_location: + row: 19 + column: 19 + fix: ~ + parent: ~ +- kind: + PathlibIsLink: ~ + location: + row: 20 + column: 8 + end_location: + row: 20 + column: 20 + fix: ~ + parent: ~ +- kind: + PathlibReadlink: ~ + location: + row: 21 + column: 0 + end_location: + row: 21 + column: 12 + fix: ~ + parent: ~ +- kind: + PathlibStat: ~ + location: + row: 22 + column: 0 + end_location: + row: 22 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibIsAbs: ~ + location: + row: 23 + column: 0 + end_location: + row: 23 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibJoin: ~ + location: + row: 24 + column: 0 + end_location: + row: 24 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibBasename: ~ + location: + row: 25 + column: 0 + end_location: + row: 25 + column: 14 + fix: ~ + parent: ~ +- kind: + PathlibDirname: ~ + location: + row: 26 + column: 0 + end_location: + row: 26 + column: 13 + fix: ~ + parent: ~ +- kind: + PathlibSamefile: ~ + location: + row: 27 + column: 0 + end_location: + row: 27 + column: 14 + fix: ~ + parent: ~ +- kind: + PathlibSplitext: ~ + location: + row: 28 + column: 0 + end_location: + row: 28 + column: 14 + fix: ~ + parent: ~ + diff --git a/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from.py.snap new file mode 100644 index 0000000000000..a3f6ff105b440 --- /dev/null +++ b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from.py.snap @@ -0,0 +1,255 @@ +--- +source: src/rules/flake8_use_pathlib/mod.rs +expression: diagnostics +--- +- kind: + PathlibAbspath: ~ + location: + row: 8 + column: 4 + end_location: + row: 8 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibChmod: ~ + location: + row: 9 + column: 5 + end_location: + row: 9 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibMkdir: ~ + location: + row: 10 + column: 6 + end_location: + row: 10 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibMakedirs: ~ + location: + row: 11 + column: 0 + end_location: + row: 11 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibRename: ~ + location: + row: 12 + column: 0 + end_location: + row: 12 + column: 6 + fix: ~ + parent: ~ +- kind: + PathlibReplace: ~ + location: + row: 13 + column: 0 + end_location: + row: 13 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibRmdir: ~ + location: + row: 14 + column: 0 + end_location: + row: 14 + column: 5 + fix: ~ + parent: ~ +- kind: + PathlibRemove: ~ + location: + row: 15 + column: 0 + end_location: + row: 15 + column: 6 + fix: ~ + parent: ~ +- kind: + PathlibUnlink: ~ + location: + row: 16 + column: 0 + end_location: + row: 16 + column: 6 + fix: ~ + parent: ~ +- kind: + PathlibGetcwd: ~ + location: + row: 17 + column: 0 + end_location: + row: 17 + column: 6 + fix: ~ + parent: ~ +- kind: + PathlibExists: ~ + location: + row: 18 + column: 4 + end_location: + row: 18 + column: 10 + fix: ~ + parent: ~ +- kind: + PathlibExpanduser: ~ + location: + row: 19 + column: 5 + end_location: + row: 19 + column: 15 + fix: ~ + parent: ~ +- kind: + PathlibIsDir: ~ + location: + row: 20 + column: 6 + end_location: + row: 20 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibIsFile: ~ + location: + row: 21 + column: 7 + end_location: + row: 21 + column: 13 + fix: ~ + parent: ~ +- kind: + PathlibIsLink: ~ + location: + row: 22 + column: 8 + end_location: + row: 22 + column: 14 + fix: ~ + parent: ~ +- kind: + PathlibReadlink: ~ + location: + row: 23 + column: 0 + end_location: + row: 23 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibStat: ~ + location: + row: 24 + column: 0 + end_location: + row: 24 + column: 4 + fix: ~ + parent: ~ +- kind: + PathlibIsAbs: ~ + location: + row: 25 + column: 0 + end_location: + row: 25 + column: 5 + fix: ~ + parent: ~ +- kind: + PathlibJoin: ~ + location: + row: 26 + column: 0 + end_location: + row: 26 + column: 4 + fix: ~ + parent: ~ +- kind: + PathlibBasename: ~ + location: + row: 27 + column: 0 + end_location: + row: 27 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibDirname: ~ + location: + row: 28 + column: 0 + end_location: + row: 28 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibSamefile: ~ + location: + row: 29 + column: 0 + end_location: + row: 29 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibSplitext: ~ + location: + row: 30 + column: 0 + end_location: + row: 30 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibOpen: ~ + location: + row: 31 + column: 5 + end_location: + row: 31 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibOpen: ~ + location: + row: 33 + column: 0 + end_location: + row: 33 + column: 4 + fix: ~ + parent: ~ + diff --git a/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from_as.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from_as.py.snap new file mode 100644 index 0000000000000..f0ae20f26d990 --- /dev/null +++ b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from_as.py.snap @@ -0,0 +1,235 @@ +--- +source: src/rules/flake8_use_pathlib/mod.rs +expression: diagnostics +--- +- kind: + PathlibAbspath: ~ + location: + row: 13 + column: 4 + end_location: + row: 13 + column: 12 + fix: ~ + parent: ~ +- kind: + PathlibChmod: ~ + location: + row: 14 + column: 5 + end_location: + row: 14 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibMkdir: ~ + location: + row: 15 + column: 6 + end_location: + row: 15 + column: 12 + fix: ~ + parent: ~ +- kind: + PathlibMakedirs: ~ + location: + row: 16 + column: 0 + end_location: + row: 16 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibRename: ~ + location: + row: 17 + column: 0 + end_location: + row: 17 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibReplace: ~ + location: + row: 18 + column: 0 + end_location: + row: 18 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibRmdir: ~ + location: + row: 19 + column: 0 + end_location: + row: 19 + column: 6 + fix: ~ + parent: ~ +- kind: + PathlibRemove: ~ + location: + row: 20 + column: 0 + end_location: + row: 20 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibUnlink: ~ + location: + row: 21 + column: 0 + end_location: + row: 21 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibGetcwd: ~ + location: + row: 22 + column: 0 + end_location: + row: 22 + column: 7 + fix: ~ + parent: ~ +- kind: + PathlibExists: ~ + location: + row: 23 + column: 4 + end_location: + row: 23 + column: 11 + fix: ~ + parent: ~ +- kind: + PathlibExpanduser: ~ + location: + row: 24 + column: 5 + end_location: + row: 24 + column: 16 + fix: ~ + parent: ~ +- kind: + PathlibIsDir: ~ + location: + row: 25 + column: 6 + end_location: + row: 25 + column: 12 + fix: ~ + parent: ~ +- kind: + PathlibIsFile: ~ + location: + row: 26 + column: 7 + end_location: + row: 26 + column: 14 + fix: ~ + parent: ~ +- kind: + PathlibIsLink: ~ + location: + row: 27 + column: 8 + end_location: + row: 27 + column: 15 + fix: ~ + parent: ~ +- kind: + PathlibReadlink: ~ + location: + row: 28 + column: 0 + end_location: + row: 28 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibStat: ~ + location: + row: 29 + column: 0 + end_location: + row: 29 + column: 5 + fix: ~ + parent: ~ +- kind: + PathlibIsAbs: ~ + location: + row: 30 + column: 0 + end_location: + row: 30 + column: 6 + fix: ~ + parent: ~ +- kind: + PathlibJoin: ~ + location: + row: 31 + column: 0 + end_location: + row: 31 + column: 5 + fix: ~ + parent: ~ +- kind: + PathlibBasename: ~ + location: + row: 32 + column: 0 + end_location: + row: 32 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibDirname: ~ + location: + row: 33 + column: 0 + end_location: + row: 33 + column: 8 + fix: ~ + parent: ~ +- kind: + PathlibSamefile: ~ + location: + row: 34 + column: 0 + end_location: + row: 34 + column: 9 + fix: ~ + parent: ~ +- kind: + PathlibSplitext: ~ + location: + row: 35 + column: 0 + end_location: + row: 35 + column: 9 + fix: ~ + parent: ~ + diff --git a/src/rules/flake8_use_pathlib/violations.rs b/src/rules/flake8_use_pathlib/violations.rs new file mode 100644 index 0000000000000..602898c90f367 --- /dev/null +++ b/src/rules/flake8_use_pathlib/violations.rs @@ -0,0 +1,279 @@ +use ruff_macros::derive_message_formats; + +use crate::define_violation; +use crate::violation::Violation; + +// PTH100 +define_violation!( + pub struct PathlibAbspath; +); +impl Violation for PathlibAbspath { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.abspath` should be replaced by `.resolve()`") + } +} + +// PTH101 +define_violation!( + pub struct PathlibChmod; +); +impl Violation for PathlibChmod { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.chmod` should be replaced by `.chmod()`") + } +} + +// PTH102 +define_violation!( + pub struct PathlibMakedirs; +); +impl Violation for PathlibMakedirs { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.makedirs` should be replaced by `.mkdir(parents=True)`") + } +} + +// PTH103 +define_violation!( + pub struct PathlibMkdir; +); +impl Violation for PathlibMkdir { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.mkdir` should be replaced by `.mkdir()`") + } +} + +// PTH104 +define_violation!( + pub struct PathlibRename; +); +impl Violation for PathlibRename { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.rename` should be replaced by `.rename()`") + } +} + +// PTH105 +define_violation!( + pub struct PathlibReplace; +); +impl Violation for PathlibReplace { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.replace`should be replaced by `.replace()`") + } +} + +// PTH106 +define_violation!( + pub struct PathlibRmdir; +); +impl Violation for PathlibRmdir { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.rmdir` should be replaced by `.rmdir()`") + } +} + +// PTH107 +define_violation!( + pub struct PathlibRemove; +); +impl Violation for PathlibRemove { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.remove` should be replaced by `.unlink()`") + } +} + +// PTH108 +define_violation!( + pub struct PathlibUnlink; +); +impl Violation for PathlibUnlink { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.unlink` should be replaced by `.unlink()`") + } +} + +// PTH109 +define_violation!( + pub struct PathlibGetcwd; +); +impl Violation for PathlibGetcwd { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.getcwd()` should be replaced by `Path.cwd()`") + } +} + +// PTH110 +define_violation!( + pub struct PathlibExists; +); +impl Violation for PathlibExists { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.exists` should be replaced by `.exists()`") + } +} + +// PTH111 +define_violation!( + pub struct PathlibExpanduser; +); +impl Violation for PathlibExpanduser { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.expanduser` should be replaced by `.expanduser()`") + } +} + +// PTH112 +define_violation!( + pub struct PathlibIsDir; +); +impl Violation for PathlibIsDir { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.isdir` should be replaced by `.is_dir()`") + } +} + +// PTH113 +define_violation!( + pub struct PathlibIsFile; +); +impl Violation for PathlibIsFile { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.isfile` should be replaced by `.is_file()`") + } +} + +// PTH114 +define_violation!( + pub struct PathlibIsLink; +); +impl Violation for PathlibIsLink { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.islink` should be replaced by `.is_symlink()`") + } +} + +// PTH115 +define_violation!( + pub struct PathlibReadlink; +); +impl Violation for PathlibReadlink { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.readlink(` should be replaced by `.readlink()`") + } +} + +// PTH116 +define_violation!( + pub struct PathlibStat; +); +impl Violation for PathlibStat { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.stat` should be replaced by `.stat()` or `.owner()` or `.group()`") + } +} + +// PTH117 +define_violation!( + pub struct PathlibIsAbs; +); +impl Violation for PathlibIsAbs { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.isabs` should be replaced by `.is_absolute()`") + } +} + +// PTH118 +define_violation!( + pub struct PathlibJoin; +); +impl Violation for PathlibJoin { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.join` should be replaced by foo_path / \"bar\"") + } +} + +// PTH119 +define_violation!( + pub struct PathlibBasename; +); +impl Violation for PathlibBasename { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.basename` should be replaced by `.name`") + } +} + +// PTH120 +define_violation!( + pub struct PathlibDirname; +); +impl Violation for PathlibDirname { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.dirname` should be replaced by `.parent`") + } +} + +// PTH121 +define_violation!( + pub struct PathlibSamefile; +); +impl Violation for PathlibSamefile { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.samefile` should be replaced by `.samefile()`") + } +} + +// PTH122 +define_violation!( + pub struct PathlibSplitext; +); +impl Violation for PathlibSplitext { + #[derive_message_formats] + fn message(&self) -> String { + format!("`os.path.splitext` should be replaced by `.suffix`") + } +} + +// PTH123 +define_violation!( + pub struct PathlibOpen; +); +impl Violation for PathlibOpen { + #[derive_message_formats] + fn message(&self) -> String { + format!("`open(\"foo\")` should be replaced by`Path(\"foo\").open()`") + } +} + +// PTH124 +define_violation!( + pub struct PathlibPyPath; +); +impl Violation for PathlibPyPath { + #[derive_message_formats] + fn message(&self) -> String { + format!("`py.path` is in maintenance mode, use `pathlib` instead") + } +} diff --git a/src/rules/mod.rs b/src/rules/mod.rs index 2c4eddc9e4f25..8e58049101778 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -25,6 +25,7 @@ pub mod flake8_simplify; pub mod flake8_tidy_imports; pub mod flake8_type_checking; pub mod flake8_unused_arguments; +pub mod flake8_use_pathlib; pub mod isort; pub mod mccabe; pub mod pandas_vet;