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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
|
||||
|
||||
[[package]]
|
||||
name = "globset"
|
||||
version = "0.4.9"
|
||||
|
|
@ -1841,6 +1847,7 @@ dependencies = [
|
|||
"fern",
|
||||
"filetime",
|
||||
"getrandom 0.2.8",
|
||||
"glob",
|
||||
"globset",
|
||||
"insta",
|
||||
"itertools",
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ common-path = { version = "1.0.0" }
|
|||
dirs = { version = "4.0.0" }
|
||||
fern = { version = "0.6.1" }
|
||||
filetime = { version = "0.2.17" }
|
||||
glob = { version = "0.3.0" }
|
||||
globset = { version = "0.4.9" }
|
||||
itertools = { version = "0.10.5" }
|
||||
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.
|
||||
|
||||
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**: `["."]`
|
||||
|
||||
**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/
|
||||
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: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: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:
|
||||
|
||||
```
|
||||
∴ 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: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: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
|
||||
|
|
@ -45,7 +47,7 @@ file paths from the current working directory:
|
|||
|
||||
```
|
||||
∴ 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: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
|
||||
|
|
@ -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/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
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
[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 anyhow::{anyhow, Result};
|
||||
use glob::{glob, GlobError, Paths, PatternError};
|
||||
use regex::Regex;
|
||||
|
||||
use crate::checks_gen::CheckCodePrefix;
|
||||
|
|
@ -65,11 +66,10 @@ impl Configuration {
|
|||
.map(|pattern| Regex::new(&pattern))
|
||||
.transpose()
|
||||
.map_err(|e| anyhow!("Invalid `dummy-variable-rgx` value: {e}"))?,
|
||||
src: options.src.map(|src| {
|
||||
src.iter()
|
||||
.map(|path| fs::normalize_path_to(Path::new(path), project_root))
|
||||
.collect()
|
||||
}),
|
||||
src: options
|
||||
.src
|
||||
.map(|src| resolve_src(&src, project_root))
|
||||
.transpose()?,
|
||||
target_version: options.target_version,
|
||||
exclude: options.exclude.map(|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::{
|
||||
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;
|
||||
|
|
@ -296,12 +296,6 @@ pub fn resolve_per_file_ignores(
|
|||
.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
|
||||
/// error codes.
|
||||
fn resolve_codes(select: &[CheckCodePrefix], ignore: &[CheckCodePrefix]) -> FxHashSet<CheckCode> {
|
||||
|
|
|
|||
|
|
@ -235,8 +235,28 @@ pub struct Options {
|
|||
)]
|
||||
pub show_source: Option<bool>,
|
||||
#[option(
|
||||
doc = "The source code paths to consider, e.g., when resolving first- vs. third-party \
|
||||
imports.",
|
||||
doc = r#"
|
||||
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#"["."]"#,
|
||||
value_type = "Vec<PathBuf>",
|
||||
example = r#"
|
||||
|
|
|
|||
Loading…
Reference in New Issue