From 8a980c0b052db8c105733df081de1978bbcda065 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 15 Jun 2023 15:41:05 -0400 Subject: [PATCH] Don't treat straight imports of __future__ as '__future__' imports --- .../test/fixtures/pyflakes/F401_18.py | 11 ++++++++++ crates/ruff/src/checkers/ast/mod.rs | 19 +--------------- crates/ruff/src/rules/pyflakes/mod.rs | 1 + ...les__pyflakes__tests__F401_F401_18.py.snap | 22 +++++++++++++++++++ ..._rules__pyflakes__tests__F404_F404.py.snap | 8 ------- 5 files changed, 35 insertions(+), 26 deletions(-) create mode 100644 crates/ruff/resources/test/fixtures/pyflakes/F401_18.py create mode 100644 crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_18.py.snap diff --git a/crates/ruff/resources/test/fixtures/pyflakes/F401_18.py b/crates/ruff/resources/test/fixtures/pyflakes/F401_18.py new file mode 100644 index 0000000000000..d23a05ef483c4 --- /dev/null +++ b/crates/ruff/resources/test/fixtures/pyflakes/F401_18.py @@ -0,0 +1,11 @@ +"""Test that straight `__future__` imports are considered unused.""" + + +def f(): + import __future__ + + +def f(): + import __future__ + + print(__future__.absolute_import) diff --git a/crates/ruff/src/checkers/ast/mod.rs b/crates/ruff/src/checkers/ast/mod.rs index 6dd4cc885cf64..655422a4be562 100644 --- a/crates/ruff/src/checkers/ast/mod.rs +++ b/crates/ruff/src/checkers/ast/mod.rs @@ -805,24 +805,7 @@ where } for alias in names { - if &alias.name == "__future__" { - let name = alias.asname.as_ref().unwrap_or(&alias.name); - self.add_binding( - name, - alias.identifier(self.locator), - BindingKind::FutureImportation, - BindingFlags::empty(), - ); - - if self.enabled(Rule::LateFutureImport) { - if self.semantic.seen_futures_boundary() { - self.diagnostics.push(Diagnostic::new( - pyflakes::rules::LateFutureImport, - stmt.range(), - )); - } - } - } else if alias.name.contains('.') && alias.asname.is_none() { + if alias.name.contains('.') && alias.asname.is_none() { // Given `import foo.bar`, `name` would be "foo", and `qualified_name` would be // "foo.bar". let name = alias.name.split('.').next().unwrap(); diff --git a/crates/ruff/src/rules/pyflakes/mod.rs b/crates/ruff/src/rules/pyflakes/mod.rs index 1f8d5873255ec..87876e96d6784 100644 --- a/crates/ruff/src/rules/pyflakes/mod.rs +++ b/crates/ruff/src/rules/pyflakes/mod.rs @@ -43,6 +43,7 @@ mod tests { #[test_case(Rule::UnusedImport, Path::new("F401_15.py"))] #[test_case(Rule::UnusedImport, Path::new("F401_16.py"))] #[test_case(Rule::UnusedImport, Path::new("F401_17.py"))] + #[test_case(Rule::UnusedImport, Path::new("F401_18.py"))] #[test_case(Rule::ImportShadowedByLoopVar, Path::new("F402.py"))] #[test_case(Rule::UndefinedLocalWithImportStar, Path::new("F403.py"))] #[test_case(Rule::LateFutureImport, Path::new("F404.py"))] diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_18.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_18.py.snap new file mode 100644 index 0000000000000..d49e67f268f22 --- /dev/null +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F401_F401_18.py.snap @@ -0,0 +1,22 @@ +--- +source: crates/ruff/src/rules/pyflakes/mod.rs +--- +F401_18.py:5:12: F401 [*] `__future__` imported but unused + | +4 | def f(): +5 | import __future__ + | ^^^^^^^^^^ F401 + | + = help: Remove unused import: `future` + +ℹ Fix +2 2 | +3 3 | +4 4 | def f(): +5 |- import __future__ + 5 |+ pass +6 6 | +7 7 | +8 8 | def f(): + + diff --git a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F404_F404.py.snap b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F404_F404.py.snap index 6c63ee705bc90..feba0f8d2049a 100644 --- a/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F404_F404.py.snap +++ b/crates/ruff/src/rules/pyflakes/snapshots/ruff__rules__pyflakes__tests__F404_F404.py.snap @@ -11,12 +11,4 @@ F404.py:6:1: F404 `from __future__` imports must occur at the beginning of the f 8 | import __future__ | -F404.py:8:1: F404 `from __future__` imports must occur at the beginning of the file - | -6 | from __future__ import print_function -7 | -8 | import __future__ - | ^^^^^^^^^^^^^^^^^ F404 - | -