mirror of https://github.com/astral-sh/ruff
Add support for glob patterns in `src` (#1225)
This commit is contained in:
parent
9853b0728b
commit
92bc417e4e
|
|
@ -796,6 +796,12 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glob"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "globset"
|
name = "globset"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
|
@ -1841,6 +1847,7 @@ dependencies = [
|
||||||
"fern",
|
"fern",
|
||||||
"filetime",
|
"filetime",
|
||||||
"getrandom 0.2.8",
|
"getrandom 0.2.8",
|
||||||
|
"glob",
|
||||||
"globset",
|
"globset",
|
||||||
"insta",
|
"insta",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ common-path = { version = "1.0.0" }
|
||||||
dirs = { version = "4.0.0" }
|
dirs = { version = "4.0.0" }
|
||||||
fern = { version = "0.6.1" }
|
fern = { version = "0.6.1" }
|
||||||
filetime = { version = "0.2.17" }
|
filetime = { version = "0.2.17" }
|
||||||
|
glob = { version = "0.3.0" }
|
||||||
globset = { version = "0.4.9" }
|
globset = { version = "0.4.9" }
|
||||||
itertools = { version = "0.10.5" }
|
itertools = { version = "0.10.5" }
|
||||||
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
|
||||||
|
|
|
||||||
19
README.md
19
README.md
|
|
@ -1744,6 +1744,25 @@ show-source = true
|
||||||
|
|
||||||
The source code paths to consider, e.g., when resolving first- vs. third-party imports.
|
The source code paths to consider, e.g., when resolving first- vs. third-party imports.
|
||||||
|
|
||||||
|
As an example: given a Python package structure like:
|
||||||
|
|
||||||
|
```text
|
||||||
|
my_package/
|
||||||
|
pyproject.toml
|
||||||
|
src/
|
||||||
|
my_package/
|
||||||
|
__init__.py
|
||||||
|
foo.py
|
||||||
|
bar.py
|
||||||
|
```
|
||||||
|
|
||||||
|
The `src` directory should be included in `source` (e.g., `source = ["src"]`), such that
|
||||||
|
when resolving imports, `my_package.foo` is considered a first-party import.
|
||||||
|
|
||||||
|
This field supports globs. For example, if you have a series of Python packages in
|
||||||
|
a `python_modules` directory, `src = ["python_modules/*"]` would expand to incorporate
|
||||||
|
all of the packages in that directory.
|
||||||
|
|
||||||
**Default value**: `["."]`
|
**Default value**: `["."]`
|
||||||
|
|
||||||
**Type**: `Vec<PathBuf>`
|
**Type**: `Vec<PathBuf>`
|
||||||
|
|
|
||||||
|
|
@ -9,24 +9,26 @@ Running from the repo root should pick up and enforce the appropriate settings f
|
||||||
|
|
||||||
```
|
```
|
||||||
∴ cargo run resources/test/project/
|
∴ cargo run resources/test/project/
|
||||||
Found 4 error(s).
|
Found 5 error(s).
|
||||||
resources/test/project/examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
resources/test/project/examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||||
resources/test/project/examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
resources/test/project/examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||||
resources/test/project/src/file.py:1:8: F401 `os` imported but unused
|
resources/test/project/src/file.py:1:8: F401 `os` imported but unused
|
||||||
resources/test/project/src/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
resources/test/project/src/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
||||||
2 potentially fixable with the --fix option.
|
resources/test/project/src/import_file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||||
|
3 potentially fixable with the --fix option.
|
||||||
```
|
```
|
||||||
|
|
||||||
Running from the project directory itself should exhibit the same behavior:
|
Running from the project directory itself should exhibit the same behavior:
|
||||||
|
|
||||||
```
|
```
|
||||||
∴ cd resources/test/project/ && cargo run .
|
∴ cd resources/test/project/ && cargo run .
|
||||||
Found 4 error(s).
|
Found 5 error(s).
|
||||||
examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
examples/docs/docs/file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||||
examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||||
src/file.py:1:8: F401 `os` imported but unused
|
src/file.py:1:8: F401 `os` imported but unused
|
||||||
src/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
src/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
||||||
2 potentially fixable with the --fix option.
|
src/import_file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||||
|
3 potentially fixable with the --fix option.
|
||||||
```
|
```
|
||||||
|
|
||||||
Running from the sub-package directory should exhibit the same behavior, but omit the top-level
|
Running from the sub-package directory should exhibit the same behavior, but omit the top-level
|
||||||
|
|
@ -45,7 +47,7 @@ file paths from the current working directory:
|
||||||
|
|
||||||
```
|
```
|
||||||
∴ cargo run -- --config=resources/test/project/pyproject.toml resources/test/project/
|
∴ cargo run -- --config=resources/test/project/pyproject.toml resources/test/project/
|
||||||
Found 8 error(s).
|
Found 9 error(s).
|
||||||
resources/test/project/examples/docs/docs/concepts/file.py:1:8: F401 `os` imported but unused
|
resources/test/project/examples/docs/docs/concepts/file.py:1:8: F401 `os` imported but unused
|
||||||
resources/test/project/examples/docs/docs/concepts/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
resources/test/project/examples/docs/docs/concepts/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
||||||
resources/test/project/examples/docs/docs/file.py:1:8: F401 `os` imported but unused
|
resources/test/project/examples/docs/docs/file.py:1:8: F401 `os` imported but unused
|
||||||
|
|
@ -54,7 +56,8 @@ resources/test/project/examples/docs/docs/file.py:4:27: F401 `docs.concepts.file
|
||||||
resources/test/project/examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
resources/test/project/examples/docs/docs/file.py:8:5: F841 Local variable `x` is assigned to but never used
|
||||||
resources/test/project/src/file.py:1:8: F401 `os` imported but unused
|
resources/test/project/src/file.py:1:8: F401 `os` imported but unused
|
||||||
resources/test/project/src/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
resources/test/project/src/file.py:5:5: F841 Local variable `x` is assigned to but never used
|
||||||
5 potentially fixable with the --fix option.
|
resources/test/project/src/import_file.py:1:1: I001 Import block is un-sorted or un-formatted
|
||||||
|
6 potentially fixable with the --fix option.
|
||||||
```
|
```
|
||||||
|
|
||||||
Running from a parent directory should this "ignore" the `exclude` (hence, `concepts/file.py` gets
|
Running from a parent directory should this "ignore" the `exclude` (hence, `concepts/file.py` gets
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
src = ["."]
|
src = [".", "python_modules/*"]
|
||||||
|
extend-select = ["I001"]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import numpy as np
|
||||||
|
from app import app_file
|
||||||
|
from core import core_file
|
||||||
|
|
||||||
|
np.array([1, 2, 3])
|
||||||
|
app_file()
|
||||||
|
core_file()
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use glob::{glob, GlobError, Paths, PatternError};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::checks_gen::CheckCodePrefix;
|
use crate::checks_gen::CheckCodePrefix;
|
||||||
|
|
@ -65,11 +66,10 @@ impl Configuration {
|
||||||
.map(|pattern| Regex::new(&pattern))
|
.map(|pattern| Regex::new(&pattern))
|
||||||
.transpose()
|
.transpose()
|
||||||
.map_err(|e| anyhow!("Invalid `dummy-variable-rgx` value: {e}"))?,
|
.map_err(|e| anyhow!("Invalid `dummy-variable-rgx` value: {e}"))?,
|
||||||
src: options.src.map(|src| {
|
src: options
|
||||||
src.iter()
|
.src
|
||||||
.map(|path| fs::normalize_path_to(Path::new(path), project_root))
|
.map(|src| resolve_src(&src, project_root))
|
||||||
.collect()
|
.transpose()?,
|
||||||
}),
|
|
||||||
target_version: options.target_version,
|
target_version: options.target_version,
|
||||||
exclude: options.exclude.map(|paths| {
|
exclude: options.exclude.map(|paths| {
|
||||||
paths
|
paths
|
||||||
|
|
@ -216,3 +216,19 @@ impl Configuration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a list of source paths, which could include glob patterns, resolve the
|
||||||
|
/// matching paths.
|
||||||
|
pub fn resolve_src(src: &[String], project_root: &Path) -> Result<Vec<PathBuf>> {
|
||||||
|
let globs = src
|
||||||
|
.iter()
|
||||||
|
.map(Path::new)
|
||||||
|
.map(|path| fs::normalize_path_to(path, project_root))
|
||||||
|
.map(|path| glob(&path.to_string_lossy()))
|
||||||
|
.collect::<Result<Vec<Paths>, PatternError>>()?;
|
||||||
|
let paths: Vec<PathBuf> = globs
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect::<Result<Vec<PathBuf>, GlobError>>()?;
|
||||||
|
Ok(paths)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ use crate::settings::configuration::Configuration;
|
||||||
use crate::settings::types::{FilePattern, PerFileIgnore, PythonVersion, SerializationFormat};
|
use crate::settings::types::{FilePattern, PerFileIgnore, PythonVersion, SerializationFormat};
|
||||||
use crate::{
|
use crate::{
|
||||||
flake8_annotations, flake8_bugbear, flake8_import_conventions, flake8_quotes,
|
flake8_annotations, flake8_bugbear, flake8_import_conventions, flake8_quotes,
|
||||||
flake8_tidy_imports, fs, isort, mccabe, pep8_naming, pyupgrade,
|
flake8_tidy_imports, isort, mccabe, pep8_naming, pyupgrade,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod configuration;
|
pub mod configuration;
|
||||||
|
|
@ -296,12 +296,6 @@ pub fn resolve_per_file_ignores(
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_src(src: Vec<PathBuf>, project_root: &Path) -> Vec<PathBuf> {
|
|
||||||
src.into_iter()
|
|
||||||
.map(|path| fs::normalize_path_to(&path, project_root))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a set of selected and ignored prefixes, resolve the set of enabled
|
/// Given a set of selected and ignored prefixes, resolve the set of enabled
|
||||||
/// error codes.
|
/// error codes.
|
||||||
fn resolve_codes(select: &[CheckCodePrefix], ignore: &[CheckCodePrefix]) -> FxHashSet<CheckCode> {
|
fn resolve_codes(select: &[CheckCodePrefix], ignore: &[CheckCodePrefix]) -> FxHashSet<CheckCode> {
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,28 @@ pub struct Options {
|
||||||
)]
|
)]
|
||||||
pub show_source: Option<bool>,
|
pub show_source: Option<bool>,
|
||||||
#[option(
|
#[option(
|
||||||
doc = "The source code paths to consider, e.g., when resolving first- vs. third-party \
|
doc = r#"
|
||||||
imports.",
|
The source code paths to consider, e.g., when resolving first- vs. third-party imports.
|
||||||
|
|
||||||
|
As an example: given a Python package structure like:
|
||||||
|
|
||||||
|
```text
|
||||||
|
my_package/
|
||||||
|
pyproject.toml
|
||||||
|
src/
|
||||||
|
my_package/
|
||||||
|
__init__.py
|
||||||
|
foo.py
|
||||||
|
bar.py
|
||||||
|
```
|
||||||
|
|
||||||
|
The `src` directory should be included in `source` (e.g., `source = ["src"]`), such that
|
||||||
|
when resolving imports, `my_package.foo` is considered a first-party import.
|
||||||
|
|
||||||
|
This field supports globs. For example, if you have a series of Python packages in
|
||||||
|
a `python_modules` directory, `src = ["python_modules/*"]` would expand to incorporate
|
||||||
|
all of the packages in that directory.
|
||||||
|
"#,
|
||||||
default = r#"["."]"#,
|
default = r#"["."]"#,
|
||||||
value_type = "Vec<PathBuf>",
|
value_type = "Vec<PathBuf>",
|
||||||
example = r#"
|
example = r#"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue