Skip to content

Commit

Permalink
[flake8-use-pathlib] Implement glob (PTH207)
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrugman committed Jul 21, 2023
1 parent b3d3102 commit f75a68a
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 1 deletion.
10 changes: 10 additions & 0 deletions crates/ruff/resources/test/fixtures/flake8_use_pathlib/PTH207.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import os
import glob
from glob import glob as search


extensions_dir = "./extensions"

# PTH207
glob.glob(os.path.join(extensions_dir, "ops", "autograd", "*.cpp"))
search("*.png")
1 change: 1 addition & 0 deletions crates/ruff/src/checkers/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3004,6 +3004,7 @@ where
Rule::OsPathGetatime,
Rule::OsPathGetmtime,
Rule::OsPathGetctime,
Rule::Glob,
]) {
flake8_use_pathlib::rules::replaceable_by_pathlib(self, func);
}
Expand Down
1 change: 1 addition & 0 deletions crates/ruff/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Flake8UsePathlib, "203") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetatime),
(Flake8UsePathlib, "204") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetmtime),
(Flake8UsePathlib, "205") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::OsPathGetctime),
(Flake8UsePathlib, "207") => (RuleGroup::Unspecified, rules::flake8_use_pathlib::rules::Glob),

// flake8-logging-format
(Flake8LoggingFormat, "001") => (RuleGroup::Unspecified, rules::flake8_logging_format::violations::LoggingStringFormat),
Expand Down
1 change: 1 addition & 0 deletions crates/ruff/src/rules/flake8_use_pathlib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ mod tests {
#[test_case(Rule::OsPathGetatime, Path::new("PTH203.py"))]
#[test_case(Rule::OsPathGetmtime, Path::new("PTH204.py"))]
#[test_case(Rule::OsPathGetctime, Path::new("PTH205.py"))]
#[test_case(Rule::Glob, Path::new("PTH207.py"))]
fn rules_pypath(rule_code: Rule, path: &Path) -> Result<()> {
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
let diagnostics = test_path(
Expand Down
41 changes: 41 additions & 0 deletions crates/ruff/src/rules/flake8_use_pathlib/rules/glob_rule.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use ruff_diagnostics::Violation;
use ruff_macros::{derive_message_formats, violation};

/// ## What it does
/// Checks for the use of `glob`.
///
/// ## Why is this bad?
/// `pathlib` offers a high-level API for path manipulation, as compared to
/// the lower-level API offered by `os` and `glob`.
///
/// When possible, using `Path` object methods such as `Path.stat()` can
/// improve readability over their low-level counterparts (e.g.,
/// `glob.glob()`).
///
/// ## Example
/// ```python
/// import glob
/// import os
///
/// glob.glob(os.path.join(path, "requirements*.txt"))
/// ```
///
/// Use instead:
/// ```python
/// from pathlib import Path
///
/// Path(path).glob("requirements*.txt")
///
/// ## References
/// - [Python documentation: `Path.glob`](https://docs.python.org/3/library/pathlib.html#pathlib.Path.glob)
/// - [Python documentation: `glob.glob`](https://docs.python.org/3/library/glob.html#glob.glob)
/// ```
#[violation]
pub struct Glob;

impl Violation for Glob {
#[derive_message_formats]
fn message(&self) -> String {
format!("Replace `glob` with `Path.glob`")
}
}
2 changes: 2 additions & 0 deletions crates/ruff/src/rules/flake8_use_pathlib/rules/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
pub(crate) use glob_rule::*;
pub(crate) use os_path_getatime::*;
pub(crate) use os_path_getctime::*;
pub(crate) use os_path_getmtime::*;
pub(crate) use os_path_getsize::*;
pub(crate) use path_constructor_current_directory::*;
pub(crate) use replaceable_by_pathlib::*;

mod glob_rule;
mod os_path_getatime;
mod os_path_getctime;
mod os_path_getmtime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ruff_diagnostics::{Diagnostic, DiagnosticKind};
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
use crate::rules::flake8_use_pathlib::rules::{
OsPathGetatime, OsPathGetctime, OsPathGetmtime, OsPathGetsize,
Glob, OsPathGetatime, OsPathGetctime, OsPathGetmtime, OsPathGetsize,
};
use crate::rules::flake8_use_pathlib::violations::{
BuiltinOpen, OsChmod, OsGetcwd, OsMakedirs, OsMkdir, OsPathAbspath, OsPathBasename,
Expand Down Expand Up @@ -89,6 +89,8 @@ pub(crate) fn replaceable_by_pathlib(checker: &mut Checker, expr: &Expr) {
["" | "builtin", "open"] => Some(BuiltinOpen.into()),
// PTH124
["py", "path", "local"] => Some(PyPath.into()),
// PTH207
["glob", "glob"] => Some(Glob.into()),
// PTH115
// Python 3.9+
["os", "readlink"] if checker.settings.target_version >= PythonVersion::Py39 => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
source: crates/ruff/src/rules/flake8_use_pathlib/mod.rs
---
PTH207.py:9:1: PTH207 Replace `glob` with `Path.glob`
|
8 | # PTH207
9 | glob.glob(os.path.join(extensions_dir, "ops", "autograd", "*.cpp"))
| ^^^^^^^^^ PTH207
10 | search("*.png")
|

PTH207.py:10:1: PTH207 Replace `glob` with `Path.glob`
|
8 | # PTH207
9 | glob.glob(os.path.join(extensions_dir, "ops", "autograd", "*.cpp"))
10 | search("*.png")
| ^^^^^^ PTH207
|


1 change: 1 addition & 0 deletions ruff.schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f75a68a

Please sign in to comment.