Base INP check on package inference (#2079)
If a file doesn't have a `package`, then it must both be in a directory that lacks an `__init__.py`, and a directory that _isn't_ marked as a namespace package. Closes #2075.
This commit is contained in:
0
resources/test/fixtures/flake8_no_pep420/test_pass_namespace_package/example.py
vendored
Normal file
0
resources/test/fixtures/flake8_no_pep420/test_pass_namespace_package/example.py
vendored
Normal file
@@ -4,12 +4,16 @@ use crate::registry::{Diagnostic, Rule};
|
||||
use crate::rules::flake8_no_pep420::rules::implicit_namespace_package;
|
||||
use crate::settings::Settings;
|
||||
|
||||
pub fn check_file_path(path: &Path, settings: &Settings) -> Vec<Diagnostic> {
|
||||
pub fn check_file_path(
|
||||
path: &Path,
|
||||
package: Option<&Path>,
|
||||
settings: &Settings,
|
||||
) -> 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) {
|
||||
if let Some(diagnostic) = implicit_namespace_package(path, package) {
|
||||
diagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ use crate::directives::Directives;
|
||||
use crate::doc_lines::{doc_lines_from_ast, doc_lines_from_tokens};
|
||||
use crate::message::{Message, Source};
|
||||
use crate::noqa::add_noqa;
|
||||
#[cfg(test)]
|
||||
use crate::packaging::detect_package_root;
|
||||
use crate::registry::{Diagnostic, LintSource, Rule};
|
||||
use crate::settings::{flags, Settings};
|
||||
use crate::source_code::{Indexer, Locator, Stylist};
|
||||
@@ -69,7 +71,7 @@ pub fn check_path(
|
||||
.iter_enabled()
|
||||
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::Filesystem))
|
||||
{
|
||||
diagnostics.extend(check_file_path(path, settings));
|
||||
diagnostics.extend(check_file_path(path, package, settings));
|
||||
}
|
||||
|
||||
// Run the AST-based rules.
|
||||
@@ -395,7 +397,8 @@ pub fn test_path(path: &Path, settings: &Settings) -> Result<Vec<Diagnostic>> {
|
||||
directives::extract_directives(&tokens, directives::Flags::from_settings(settings));
|
||||
let mut diagnostics = check_path(
|
||||
path,
|
||||
None,
|
||||
path.parent()
|
||||
.and_then(|parent| detect_package_root(parent, &settings.namespace_packages)),
|
||||
&contents,
|
||||
tokens,
|
||||
&locator,
|
||||
|
||||
@@ -3,7 +3,7 @@ pub(crate) mod rules;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::Result;
|
||||
use test_case::test_case;
|
||||
@@ -12,11 +12,12 @@ mod tests {
|
||||
use crate::registry::Rule;
|
||||
use crate::settings::Settings;
|
||||
|
||||
#[test_case(Path::new("test_pass"); "INP001_0")]
|
||||
#[test_case(Path::new("test_pass_init"); "INP001_0")]
|
||||
#[test_case(Path::new("test_fail_empty"); "INP001_1")]
|
||||
#[test_case(Path::new("test_fail_nonempty"); "INP001_2")]
|
||||
#[test_case(Path::new("test_fail_shebang"); "INP001_3")]
|
||||
#[test_case(Path::new("test_ignored"); "INP001_4")]
|
||||
#[test_case(Path::new("test_pass_namespace_package"); "INP001_5")]
|
||||
fn test_flake8_no_pep420(path: &Path) -> Result<()> {
|
||||
let snapshot = format!("{}", path.to_string_lossy());
|
||||
let diagnostics = test_path(
|
||||
@@ -24,7 +25,12 @@ mod tests {
|
||||
.join(path)
|
||||
.join("example.py")
|
||||
.as_path(),
|
||||
&Settings::for_rule(Rule::ImplicitNamespacePackage),
|
||||
&Settings {
|
||||
namespace_packages: vec![PathBuf::from(
|
||||
"./resources/test/fixtures/flake8_no_pep420/test_pass_namespace_package",
|
||||
)],
|
||||
..Settings::for_rule(Rule::ImplicitNamespacePackage)
|
||||
},
|
||||
)?;
|
||||
insta::assert_yaml_snapshot!(snapshot, diagnostics);
|
||||
Ok(())
|
||||
|
||||
@@ -5,14 +5,13 @@ use crate::registry::Diagnostic;
|
||||
use crate::{fs, violations};
|
||||
|
||||
/// INP001
|
||||
pub fn implicit_namespace_package(path: &Path) -> Option<Diagnostic> {
|
||||
if let Some(parent) = path.parent() {
|
||||
if !parent.join("__init__.py").as_path().exists() {
|
||||
return Some(Diagnostic::new(
|
||||
violations::ImplicitNamespacePackage(fs::relativize_path(path).to_string()),
|
||||
Range::default(),
|
||||
));
|
||||
}
|
||||
pub fn implicit_namespace_package(path: &Path, package: Option<&Path>) -> Option<Diagnostic> {
|
||||
if package.is_none() {
|
||||
Some(Diagnostic::new(
|
||||
violations::ImplicitNamespacePackage(fs::relativize_path(path).to_string()),
|
||||
Range::default(),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
source: src/rules/flake8_no_pep420/mod.rs
|
||||
expression: diagnostics
|
||||
---
|
||||
[]
|
||||
|
||||
Reference in New Issue
Block a user