mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 12:55:05 +00:00

## Summary The implicit namespace package rule currently fails to detect cases like the following: ```text foo/ ├── __init__.py └── bar/ └── baz/ └── __init__.py ``` The problem is that we detect a root at `foo`, and then an independent root at `baz`. We _would_ detect that `bar` is an implicit namespace package, but it doesn't contain any files! So we never check it, and have no place to raise the diagnostic. This PR adds detection for these kinds of nested packages, and augments the `INP` rule to flag the `__init__.py` file above with a specialized message. As a side effect, I've introduced a dedicated `PackageRoot` struct which we can pass around in lieu of Yet Another `Path`. For now, I'm only enabling this in preview (and the approach doesn't affect any other rules). It's a bug fix, but it may end up expanding the rule. Closes https://github.com/astral-sh/ruff/issues/13519.
60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use std::path::Path;
|
|
|
|
use ruff_diagnostics::Diagnostic;
|
|
use ruff_python_trivia::CommentRanges;
|
|
|
|
use crate::package::PackageRoot;
|
|
use crate::registry::Rule;
|
|
use crate::rules::flake8_builtins::rules::builtin_module_shadowing;
|
|
use crate::rules::flake8_no_pep420::rules::implicit_namespace_package;
|
|
use crate::rules::pep8_naming::rules::invalid_module_name;
|
|
use crate::settings::LinterSettings;
|
|
use crate::Locator;
|
|
|
|
pub(crate) fn check_file_path(
|
|
path: &Path,
|
|
package: Option<PackageRoot<'_>>,
|
|
locator: &Locator,
|
|
comment_ranges: &CommentRanges,
|
|
settings: &LinterSettings,
|
|
) -> Vec<Diagnostic> {
|
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
|
|
|
// flake8-no-pep420
|
|
if settings.rules.enabled(Rule::ImplicitNamespacePackage) {
|
|
if let Some(diagnostic) = implicit_namespace_package(
|
|
path,
|
|
package,
|
|
locator,
|
|
comment_ranges,
|
|
&settings.project_root,
|
|
&settings.src,
|
|
settings.preview,
|
|
) {
|
|
diagnostics.push(diagnostic);
|
|
}
|
|
}
|
|
|
|
// pep8-naming
|
|
if settings.rules.enabled(Rule::InvalidModuleName) {
|
|
if let Some(diagnostic) =
|
|
invalid_module_name(path, package, &settings.pep8_naming.ignore_names)
|
|
{
|
|
diagnostics.push(diagnostic);
|
|
}
|
|
}
|
|
|
|
// flake8-builtins
|
|
if settings.rules.enabled(Rule::BuiltinModuleShadowing) {
|
|
if let Some(diagnostic) = builtin_module_shadowing(
|
|
path,
|
|
package,
|
|
&settings.flake8_builtins.builtins_allowed_modules,
|
|
settings.target_version,
|
|
) {
|
|
diagnostics.push(diagnostic);
|
|
}
|
|
}
|
|
|
|
diagnostics
|
|
}
|