From 666892955324605ea3764e1fd51c62b2505b7805 Mon Sep 17 00:00:00 2001 From: Simon Brugman Date: Sun, 22 Jan 2023 20:27:54 +0100 Subject: [PATCH] feat: open (PTH023) + parentheses --- README.md | 5 +++-- .../fixtures/flake8_use_pathlib/full_name.py | 3 +++ .../flake8_use_pathlib/import_from.py | 3 +++ ruff.schema.json | 1 + src/checkers/ast.rs | 1 + src/registry.rs | 1 + src/rules/flake8_use_pathlib/helpers.rs | 8 ++++++-- src/rules/flake8_use_pathlib/mod.rs | 1 + ...ake8_use_pathlib__tests__full_name.py.snap | 20 +++++++++++++++++++ ...e8_use_pathlib__tests__import_from.py.snap | 20 +++++++++++++++++++ src/rules/flake8_use_pathlib/violations.rs | 15 ++++++++++++-- 11 files changed, 72 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d771b5cd8c4c1..c585170c6dff2 100644 --- a/README.md +++ b/README.md @@ -1205,7 +1205,7 @@ For more, see [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/) | 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` | | +| 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()` | | @@ -1220,13 +1220,14 @@ For more, see [flake8-use-pathlib](https://pypi.org/project/flake8-use-pathlib/) | 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` | | +| 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()` | | ### Ruff-specific rules (RUF) diff --git a/resources/test/fixtures/flake8_use_pathlib/full_name.py b/resources/test/fixtures/flake8_use_pathlib/full_name.py index 6af31a02d22aa..6d6ec8ed1d0ac 100644 --- a/resources/test/fixtures/flake8_use_pathlib/full_name.py +++ b/resources/test/fixtures/flake8_use_pathlib/full_name.py @@ -26,3 +26,6 @@ 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_from.py b/resources/test/fixtures/flake8_use_pathlib/import_from.py index 3a38a6e93812d..9e4dc71a2d647 100644 --- a/resources/test/fixtures/flake8_use_pathlib/import_from.py +++ b/resources/test/fixtures/flake8_use_pathlib/import_from.py @@ -28,3 +28,6 @@ dirname(p) samefile(p) splitext(p) +with open(p) as fp: + fp.read() +open(p).close() diff --git a/ruff.schema.json b/ruff.schema.json index 5032ab4368f21..68f5d083ddd91 100644 --- a/ruff.schema.json +++ b/ruff.schema.json @@ -1661,6 +1661,7 @@ "PTH120", "PTH121", "PTH122", + "PTH123", "Q", "Q0", "Q00", diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index 3a515010b6a8a..4df5bde4c0030 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -2569,6 +2569,7 @@ where || self.settings.rules.enabled(&Rule::PathlibBasename) || self.settings.rules.enabled(&Rule::PathlibSamefile) || self.settings.rules.enabled(&Rule::PathlibSplitext) + || self.settings.rules.enabled(&Rule::PathlibOpen) { flake8_use_pathlib::helpers::replaceable_by_pathlib(self, func); } diff --git a/src/registry.rs b/src/registry.rs index 0bc562e0b8235..0e508693762f5 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -453,6 +453,7 @@ ruff_macros::define_rule_mapping!( 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, // ruff RUF001 => violations::AmbiguousUnicodeCharacterString, RUF002 => violations::AmbiguousUnicodeCharacterDocstring, diff --git a/src/rules/flake8_use_pathlib/helpers.rs b/src/rules/flake8_use_pathlib/helpers.rs index 01d6baf520b9f..74cea9be2a6fe 100644 --- a/src/rules/flake8_use_pathlib/helpers.rs +++ b/src/rules/flake8_use_pathlib/helpers.rs @@ -6,8 +6,9 @@ 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, PathlibReadlink, PathlibRemove, PathlibRename, - PathlibReplace, PathlibRmdir, PathlibSamefile, PathlibSplitext, PathlibStat, PathlibUnlink, + PathlibJoin, PathlibMakedirs, PathlibMkdir, PathlibOpen, PathlibReadlink, PathlibRemove, + PathlibRename, PathlibReplace, PathlibRmdir, PathlibSamefile, PathlibSplitext, PathlibStat, + PathlibUnlink, }; enum OsCall { @@ -34,6 +35,7 @@ enum OsCall { Dirname, Samefile, Splitext, + Open, } pub fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) { @@ -64,6 +66,7 @@ pub fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) { ["os", "path", "dirname"] => Some(OsCall::Dirname), ["os", "path", "samefile"] => Some(OsCall::Samefile), ["os", "path", "splitext"] => Some(OsCall::Splitext), + ["", "open"] => Some(OsCall::Open), _ => None, }) { @@ -92,6 +95,7 @@ pub fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) { OsCall::Dirname => PathlibDirname.into(), OsCall::Samefile => PathlibSamefile.into(), OsCall::Splitext => PathlibSplitext.into(), + OsCall::Open => PathlibOpen.into(), }, Range::from_located(expr), ); diff --git a/src/rules/flake8_use_pathlib/mod.rs b/src/rules/flake8_use_pathlib/mod.rs index b065fd2b6d833..a632d262a7839 100644 --- a/src/rules/flake8_use_pathlib/mod.rs +++ b/src/rules/flake8_use_pathlib/mod.rs @@ -47,6 +47,7 @@ mod tests { Rule::PathlibDirname, Rule::PathlibSamefile, Rule::PathlibSplitext, + Rule::PathlibOpen, ]), )?; insta::assert_yaml_snapshot!(snapshot, diagnostics); 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 index 1691e4d752c1a..d14875f4966b5 100644 --- 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 @@ -232,4 +232,24 @@ expression: diagnostics 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_from.py.snap b/src/rules/flake8_use_pathlib/snapshots/ruff__rules__flake8_use_pathlib__tests__import_from.py.snap index 3eb1d2c4ccf1b..a3f6ff105b440 100644 --- 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 @@ -232,4 +232,24 @@ expression: diagnostics 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/violations.rs b/src/rules/flake8_use_pathlib/violations.rs index 0f55f086c7b59..fa59d098fc446 100644 --- a/src/rules/flake8_use_pathlib/violations.rs +++ b/src/rules/flake8_use_pathlib/violations.rs @@ -21,7 +21,7 @@ define_violation!( impl Violation for PathlibChmod { #[derive_message_formats] fn message(&self) -> String { - format!("`os.chmod` should be replaced by `.chmod`") + format!("`os.chmod` should be replaced by `.chmod()`") } } @@ -186,7 +186,7 @@ define_violation!( impl Violation for PathlibStat { #[derive_message_formats] fn message(&self) -> String { - format!("`os.stat` should be replaced by `.stat()` or `.owner()` or `.group`") + format!("`os.stat` should be replaced by `.stat()` or `.owner()` or `.group()`") } } @@ -255,3 +255,14 @@ impl Violation for PathlibSplitext { 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()`") + } +}