Don't walk past project root when figuring out exclusion (#2471)

This commit is contained in:
Aarni Koskela 2023-02-03 15:23:51 +02:00 committed by GitHub
parent a26b1f43e9
commit ae20a721a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 49 additions and 1 deletions

View file

@ -1,2 +1,7 @@
[tool.ruff]
src = ["."]
# This will make sure that `exclude` paths are rooted
# to where the configuration file was found; this file exists
# in a `resources/test` hierarchy.
exclude = ["resources"]

View file

@ -0,0 +1,4 @@
# This file should be ignored, but it would otherwise trigger
# an unused import error:
import math

View file

@ -411,6 +411,11 @@ fn is_file_excluded(
return true;
}
}
if path == settings.project_root {
// Bail out; we'd end up past the project root on the next iteration
// (excludes etc. are thus "rooted" to the project).
break;
}
}
false
}
@ -424,8 +429,13 @@ mod tests {
use path_absolutize::Absolutize;
use crate::fs;
use crate::resolver::{is_python_path, match_exclusion};
use crate::resolver::{
is_file_excluded, is_python_path, match_exclusion, resolve_settings_with_processor,
NoOpProcessor, PyprojectDiscovery, Relativity, Resolver,
};
use crate::settings::pyproject::find_settings_toml;
use crate::settings::types::FilePattern;
use crate::test::test_resource_path;
#[test]
fn inclusions() {
@ -567,4 +577,30 @@ mod tests {
Ok(())
}
#[test]
fn rooted_exclusion() -> Result<()> {
let package_root = test_resource_path("package");
let resolver = Resolver::default();
let ppd = PyprojectDiscovery::Hierarchical(resolve_settings_with_processor(
&find_settings_toml(&package_root)?.unwrap(),
&Relativity::Parent,
&NoOpProcessor,
)?);
// src/app.py should not be excluded even if it lives in a hierarchy that should be
// excluded by virtue of the pyproject.toml having `resources/*` in it.
assert!(!is_file_excluded(
&package_root.join("src/app.py"),
&resolver,
&ppd,
));
// However, resources/ignored.py should be ignored, since that `resources` is beneath
// the package root.
assert!(is_file_excluded(
&package_root.join("resources/ignored.py"),
&resolver,
&ppd,
));
Ok(())
}
}

View file

@ -71,6 +71,7 @@ impl Default for Settings {
respect_gitignore: true,
show_source: false,
src: vec![path_dedot::CWD.clone()],
project_root: path_dedot::CWD.clone(),
target_version: TARGET_VERSION,
task_tags: TASK_TAGS.iter().map(ToString::to_string).collect(),
typing_modules: vec![],

View file

@ -90,6 +90,7 @@ pub struct Settings {
pub extend_exclude: HashableGlobSet,
pub force_exclude: bool,
pub respect_gitignore: bool,
pub project_root: PathBuf,
// Rule-specific settings
pub allowed_confusables: HashableHashSet<char>,
@ -167,6 +168,7 @@ impl Settings {
src: config
.src
.unwrap_or_else(|| vec![project_root.to_path_buf()]),
project_root: project_root.to_path_buf(),
target_version: config.target_version.unwrap_or(defaults::TARGET_VERSION),
task_tags: config.task_tags.unwrap_or_else(|| {
defaults::TASK_TAGS