Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/unimport/statement.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,26 @@ class Name:
def is_attribute(self):
return "." in self.name

def _is_deferred_usage(self, imp: Import | ImportFrom) -> bool:
imp_scope = imp.scope
scope = self.scope
while scope is not None and scope != imp_scope:
if isinstance(scope.node, (ast.FunctionDef, ast.AsyncFunctionDef)):
return True
scope = scope.parent
return False

def match_2(self, imp: Import | ImportFrom) -> bool:
if self.is_all:
is_match = self.name == imp.name
elif self.is_attribute:
is_match = imp.lineno < self.lineno and (
is_match = (imp.lineno < self.lineno or self._is_deferred_usage(imp)) and (
".".join(self.name.split(".")[: len(imp)]) == imp.name or imp.is_match_sub_packages(self.name)
)
else:
is_match = (imp.lineno < self.lineno) and (self.name == imp.name or imp.is_match_sub_packages(self.name))
is_match = (imp.lineno < self.lineno or self._is_deferred_usage(imp)) and (
self.name == imp.name or imp.is_match_sub_packages(self.name)
)

return is_match

Expand Down
14 changes: 14 additions & 0 deletions tests/cases/analyzer/unused/from_import_after_use_in_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=2, name="path.join", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
ImportFrom(lineno=4, column=1, name="path", package="os", star=False, suggestions=[]),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = []
17 changes: 17 additions & 0 deletions tests/cases/analyzer/unused/import_after_use_at_module_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=1, name="print", is_all=False),
Name(lineno=1, name="sys.path", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=3, column=1, name="sys", package="sys"),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=3, column=1, name="sys", package="sys"),
]
15 changes: 15 additions & 0 deletions tests/cases/analyzer/unused/import_after_use_in_async_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=2, name="print", is_all=False),
Name(lineno=2, name="sys.path", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=4, column=1, name="sys", package="sys"),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = []
17 changes: 17 additions & 0 deletions tests/cases/analyzer/unused/import_after_use_in_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=2, name="x", is_all=False),
Name(lineno=2, name="sys.platform", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=4, column=1, name="sys", package="sys"),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=4, column=1, name="sys", package="sys"),
]
15 changes: 15 additions & 0 deletions tests/cases/analyzer/unused/import_after_use_in_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=2, name="print", is_all=False),
Name(lineno=2, name="sys.path", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=4, column=1, name="sys", package="sys"),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = []
14 changes: 14 additions & 0 deletions tests/cases/analyzer/unused/import_after_use_in_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=3, name="os.getcwd", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=5, column=1, name="os", package="os"),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = []
16 changes: 16 additions & 0 deletions tests/cases/analyzer/unused/import_after_use_in_nested_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import Union

from unimport.statement import Import, ImportFrom, Name

__all__ = ["NAMES", "IMPORTS", "UNUSED_IMPORTS"]


NAMES: list[Name] = [
Name(lineno=3, name="print", is_all=False),
Name(lineno=3, name="os.path.join", is_all=False),
Name(lineno=3, name="os.path", is_all=False),
]
IMPORTS: list[Union[Import, ImportFrom]] = [
Import(lineno=5, column=1, name="os", package="os"),
]
UNUSED_IMPORTS: list[Union[Import, ImportFrom]] = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def foo():
return path.join("a", "b")

from os import path
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
print(sys.path)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
async def bob():
print(sys.path)

import sys
2 changes: 2 additions & 0 deletions tests/cases/refactor/unused/import_after_use_in_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class Foo:
x = sys.platform
4 changes: 4 additions & 0 deletions tests/cases/refactor/unused/import_after_use_in_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def bob():
print(sys.path)

import sys
5 changes: 5 additions & 0 deletions tests/cases/refactor/unused/import_after_use_in_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Foo:
def bar(self):
return os.getcwd()

import os
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def outer():
def inner():
print(os.path.join("a", "b"))

import os
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def foo():
return path.join("a", "b")

from os import path
3 changes: 3 additions & 0 deletions tests/cases/source/unused/import_after_use_at_module_level.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
print(sys.path)

import sys
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
async def bob():
print(sys.path)

import sys
4 changes: 4 additions & 0 deletions tests/cases/source/unused/import_after_use_in_class.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Foo:
x = sys.platform

import sys
4 changes: 4 additions & 0 deletions tests/cases/source/unused/import_after_use_in_function.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
def bob():
print(sys.path)

import sys
5 changes: 5 additions & 0 deletions tests/cases/source/unused/import_after_use_in_method.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Foo:
def bar(self):
return os.getcwd()

import os
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def outer():
def inner():
print(os.path.join("a", "b"))

import os