[pyflakes] Fix allowed-unused-imports matching for top-level modules (F401) (#20115)

<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

Fixes #19664

Fix allowed unused imports matching for top-level modules.

I've simply replaced `from_dotted_name` with `user_defined`. Since
QualifiedName for imports is created in
crates/ruff_python_semantic/src/imports.rs, I guess it's acceptable to
use `user_defined` here. Please tell me if there is better way.


0c5089ed9e/crates/ruff_python_semantic/src/imports.rs (L62)

## Test Plan

<!-- How was it tested? -->

I've added a snapshot test
`f401_allowed_unused_imports_top_level_module`.
This commit is contained in:
Takayuki Maeda 2025-08-28 22:02:50 +09:00 committed by GitHub
parent 1ce65714c0
commit 76a6b7e3e2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 37 additions and 1 deletions

View file

@ -0,0 +1,16 @@
"""
Test: allowed-unused-imports-top-level-module
"""
# No errors
def f():
import hvplot
def f():
import hvplot.pandas
def f():
import hvplot.pandas.plots
def f():
from hvplot.pandas import scatter_matrix
def f():
from hvplot.pandas.plots import scatter_matrix

View file

@ -376,6 +376,22 @@ mod tests {
Ok(())
}
#[test_case(Rule::UnusedImport, Path::new("F401_35.py"))]
fn f401_allowed_unused_imports_top_level_module(rule_code: Rule, path: &Path) -> Result<()> {
let diagnostics = test_path(
Path::new("pyflakes").join(path).as_path(),
&LinterSettings {
pyflakes: pyflakes::settings::Settings {
allowed_unused_imports: vec!["hvplot".to_string()],
..pyflakes::settings::Settings::default()
},
..LinterSettings::for_rule(rule_code)
},
)?;
assert_diagnostics!(diagnostics);
Ok(())
}
#[test]
fn f841_dummy_variable_rgx() -> Result<()> {
let diagnostics = test_path(

View file

@ -334,7 +334,7 @@ pub(crate) fn unused_import(checker: &Checker, scope: &Scope) {
.allowed_unused_imports
.iter()
.any(|allowed_unused_import| {
let allowed_unused_import = QualifiedName::from_dotted_name(allowed_unused_import);
let allowed_unused_import = QualifiedName::user_defined(allowed_unused_import);
import.qualified_name().starts_with(&allowed_unused_import)
})
{

View file

@ -0,0 +1,4 @@
---
source: crates/ruff_linter/src/rules/pyflakes/mod.rs
---