diff --git a/crates/ruff/tests/lint.rs b/crates/ruff/tests/lint.rs index 474f62dd4fb28..0bd542bae7b80 100644 --- a/crates/ruff/tests/lint.rs +++ b/crates/ruff/tests/lint.rs @@ -2300,13 +2300,11 @@ fn a005_module_shadowing_strict() -> Result<()> { ----- stdout ----- abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module collections/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - collections/abc/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - collections/foobar/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module + collections/abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module foobar/abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module foobar/collections/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - foobar/collections/abc/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - foobar/collections/foobar/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - Found 8 errors. + foobar/collections/abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module + Found 6 errors. ----- stderr ----- "); @@ -2342,13 +2340,11 @@ fn a005_module_shadowing_strict() -> Result<()> { ----- stdout ----- abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module collections/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - collections/abc/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - collections/foobar/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module + collections/abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module foobar/abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module foobar/collections/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - foobar/collections/abc/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - foobar/collections/foobar/__init__.py:1:1: A005 Module `collections` shadows a Python standard-library module - Found 8 errors. + foobar/collections/abc/__init__.py:1:1: A005 Module `abc` shadows a Python standard-library module + Found 6 errors. ----- stderr ----- "); diff --git a/crates/ruff_linter/src/rules/flake8_builtins/rules/stdlib_module_shadowing.rs b/crates/ruff_linter/src/rules/flake8_builtins/rules/stdlib_module_shadowing.rs index 726002e0a05b1..6451d8bd195a2 100644 --- a/crates/ruff_linter/src/rules/flake8_builtins/rules/stdlib_module_shadowing.rs +++ b/crates/ruff_linter/src/rules/flake8_builtins/rules/stdlib_module_shadowing.rs @@ -79,28 +79,31 @@ pub(crate) fn stdlib_module_shadowing( Cow::from(path.with_extension("")) }; - // convert a filesystem path like `foobar/collections/abc` to a sequence of modules like - // `["foobar", "collections", "abc"]`, stripping anything that's not a normal component - for component in path + // convert a filesystem path like `foobar/collections/abc` to a reversed sequence of modules + // like `["foobar", "collections", "abc"]`, stripping anything that's not a normal component + let mut components = path .components() .filter(|c| matches!(c, Component::Normal(_))) - .map(|c| c.as_os_str().to_string_lossy()) - { - if !is_allowed_module(settings, &component) { - return Some(Diagnostic::new( - StdlibModuleShadowing { - name: component.to_string(), - }, - TextRange::default(), - )); - } - // in non-strict mode we only consider the first component - if !settings.flake8_builtins.builtins_strict_checking { - break; - } + .map(|c| c.as_os_str().to_string_lossy()); + + // in strict mode, check the last path component, matching the upstream rule. in non-strict + // mode, only compare the first component (the root package) + let module_name = if settings.flake8_builtins.builtins_strict_checking { + components.last()? + } else { + components.next()? + }; + + if is_allowed_module(settings, &module_name) { + return None; } - None + Some(Diagnostic::new( + StdlibModuleShadowing { + name: module_name.to_string(), + }, + TextRange::default(), + )) } /// Return the longest prefix of `path` between `settings.src` and `settings.project_root`.