mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 20:42:10 +00:00
Detect empty implicit namespace packages (#14236)
## 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.
This commit is contained in:
parent
94dee2a36d
commit
c7d48e10e6
26 changed files with 282 additions and 83 deletions
|
@ -2,20 +2,20 @@ use std::borrow::Cow;
|
|||
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use ruff_linter::{
|
||||
linter::{FixerResult, LinterResult},
|
||||
packaging::detect_package_root,
|
||||
settings::{flags, types::UnsafeFixes, LinterSettings},
|
||||
};
|
||||
use ruff_notebook::SourceValue;
|
||||
use ruff_source_file::LineIndex;
|
||||
|
||||
use crate::{
|
||||
edit::{Replacement, ToRangeExt},
|
||||
resolve::is_document_excluded,
|
||||
session::DocumentQuery,
|
||||
PositionEncoding,
|
||||
};
|
||||
use ruff_linter::package::PackageRoot;
|
||||
use ruff_linter::{
|
||||
linter::{FixerResult, LinterResult},
|
||||
packaging::detect_package_root,
|
||||
settings::{flags, types::UnsafeFixes, LinterSettings},
|
||||
};
|
||||
use ruff_notebook::SourceValue;
|
||||
use ruff_source_file::LineIndex;
|
||||
|
||||
/// A simultaneous fix made across a single text document or among an arbitrary
|
||||
/// number of notebook cells.
|
||||
|
@ -49,6 +49,7 @@ pub(crate) fn fix_all(
|
|||
.expect("a path to a document should have a parent path"),
|
||||
&linter_settings.namespace_packages,
|
||||
)
|
||||
.map(PackageRoot::root)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
@ -3,7 +3,14 @@
|
|||
use rustc_hash::FxHashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
edit::{NotebookRange, ToRangeExt},
|
||||
resolve::is_document_excluded,
|
||||
session::DocumentQuery,
|
||||
PositionEncoding, DIAGNOSTIC_NAME,
|
||||
};
|
||||
use ruff_diagnostics::{Applicability, Diagnostic, DiagnosticKind, Edit, Fix};
|
||||
use ruff_linter::package::PackageRoot;
|
||||
use ruff_linter::{
|
||||
directives::{extract_directives, Flags},
|
||||
generate_noqa_edits,
|
||||
|
@ -21,13 +28,6 @@ use ruff_python_parser::ParseError;
|
|||
use ruff_source_file::LineIndex;
|
||||
use ruff_text_size::{Ranged, TextRange};
|
||||
|
||||
use crate::{
|
||||
edit::{NotebookRange, ToRangeExt},
|
||||
resolve::is_document_excluded,
|
||||
session::DocumentQuery,
|
||||
PositionEncoding, DIAGNOSTIC_NAME,
|
||||
};
|
||||
|
||||
/// This is serialized on the diagnostic `data` field.
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub(crate) struct AssociatedDiagnosticData {
|
||||
|
@ -89,6 +89,7 @@ pub(crate) fn check(
|
|||
.expect("a path to a document should have a parent path"),
|
||||
&linter_settings.namespace_packages,
|
||||
)
|
||||
.map(PackageRoot::root)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue