def test_import_in_function(self): self.assertSourceAfterScanningEqualToExpected( """\ import t from l import t from x import y, z, t def function(f=t): import x return f from i import t, ii print(t) """, [ Import( lineno=1, column=1, name="t", package="t", ), ImportFrom( lineno=2, column=1, name="t", package="l", star=False, suggestions=[], ), ImportFrom( lineno=3, column=1, name="y", package="x", star=False, suggestions=[], ), ImportFrom( lineno=3, column=2, name="z", package="x", star=False, suggestions=[], ), Import( lineno=6, column=1, name="x", package="x", ), ImportFrom( lineno=8, column=2, name="ii", package="i", star=False, suggestions=[], ), ], )
def test_full_unused(self): source = ( "from x import y\n" "from x import y\n" "from t import x\n" "import re\n" "import ll\n" "import ll\n" "from c import e\n" "import e\n" ) expected_unused_imports = [ ImportFrom( lineno=1, column=1, suggestions=[], name="y", star=False ), ImportFrom( lineno=2, column=1, suggestions=[], name="y", star=False ), ImportFrom( lineno=3, column=1, suggestions=[], name="x", star=False ), Import(lineno=4, column=1, name="re"), Import(lineno=5, column=1, name="ll"), Import(lineno=6, column=1, name="ll"), ImportFrom( lineno=7, column=1, suggestions=[], name="e", star=False ), Import(lineno=8, column=1, name="e"), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_three_used(self): source = ("from x import y\n" "from x import y\n" "from t import x\n" "import re\n" "import ll\n" "import ll\n" "from c import e\n" "import e\n" "from pathlib import Path\n" "from pathlib import Path\n" "p = Path()\n" "print(ll)\n" "def function(e=e):pass\n") expected_unused_imports = [ ImportFrom(lineno=1, name="y", star=False, module=None, modules=[]), ImportFrom(lineno=2, name="y", star=False, module=None, modules=[]), ImportFrom(lineno=3, name="x", star=False, module=None, modules=[]), Import(lineno=4, name="re", module=re), Import(lineno=5, name="ll", module=None), ImportFrom(lineno=7, name="e", star=False, module=None, modules=[]), ImportFrom(lineno=9, name="Path", star=False, module=pathlib, modules=[]), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_import_in_function(self): source = ("import t\n" "from l import t\n" "from x import y, z, t\n\n" "def function(f=t):\n" " import x\n" " return f\n" "from i import t, ii\n" "print(t)\n") expected_unused_imports = [ Import(lineno=1, name="t", module=None), ImportFrom(lineno=2, name="t", star=False, module=None, modules=[]), ImportFrom(lineno=3, name="y", star=False, module=None, modules=[]), ImportFrom(lineno=3, name="z", star=False, module=None, modules=[]), Import(lineno=6, name="x", module=None), ImportFrom(lineno=8, name="ii", star=False, module=None, modules=[]), ] self.assertUnimportEqual(source, expected_unused_imports)
def visit_Import(self, node: ast.Import) -> None: if self.skip_import(node): return None for column, alias in enumerate(node.names): Import.register( lineno=node.lineno, column=column + 1, name=(alias.asname or alias.name), package=alias.name, node=node, )
def test_full_unused(self): self.assertSourceAfterScanningEqualToExpected( """\ from x import y from x import y from t import x import re import ll import ll from c import e import e """, [ ImportFrom( lineno=1, column=1, suggestions=[], name="y", package="x", star=False, ), ImportFrom( lineno=2, column=1, suggestions=[], name="y", package="x", star=False, ), ImportFrom( lineno=3, column=1, suggestions=[], name="x", package="t", star=False, ), Import(lineno=4, column=1, name="re", package="re"), Import(lineno=5, column=1, name="ll", package="ll"), Import(lineno=6, column=1, name="ll", package="ll"), ImportFrom( lineno=7, column=1, suggestions=[], name="e", package="c", star=False, ), Import(lineno=8, column=1, name="e", package="e"), ], )
def test_import_in_function_used_two_different(self): source = ( "import t\n" "print(t)\n\n" "from l import t\n" "from x import y, z, t\n\n" "def function(f=t):\n" " import x\n" " return f\n" "from i import t, ii\n" "print(t)\n" ) expected_unused_imports = [ ImportFrom( lineno=4, column=1, name="t", star=False, suggestions=[] ), ImportFrom( lineno=5, column=1, name="y", star=False, suggestions=[] ), ImportFrom( lineno=5, column=2, name="z", star=False, suggestions=[] ), Import( lineno=8, column=1, name="x", ), ImportFrom( lineno=10, column=2, name="ii", star=False, suggestions=[] ), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_cases(path: Path, refactor_path: Path, analyzer_path: Path, logger): case_path = f"{path.parent.name}/{path.name}" analyzer_path_ = analyzer_path / case_path refactor_path_ = refactor_path / case_path logger.debug(f"Source path: {path}") logger.debug(f"Analyzer path: {analyzer_path_}") logger.debug(f"Refactor path: {refactor_path_}") # analyzer tests analyzer_import_path = ".".join(analyzer_path_.parts[:-1]) analyzer_import_path += f".{path.stem}" analyzer = importlib.import_module(analyzer_import_path) source = path.read_text() skip = re.search( "# skip; condition: (?P<condition>.*), reason: (?P<reason>.*)", source, re.IGNORECASE, ) if skip: condition = skip.group("condition") if condition in ["not PY38_PLUS"] and eval(condition): reason = skip.group("reason") pytest.skip(reason, allow_module_level=True) with Analyzer(source=source, include_star_import=True): assert Name.names == analyzer.NAMES assert Import.imports == analyzer.IMPORTS assert list(Import.get_unused_imports()) == analyzer.UNUSED_IMPORTS # refactor tests refactor = refactor_string(source, analyzer.UNUSED_IMPORTS) refactor_path_.write_text(refactor) assert refactor_path_.read_text() == refactor
def test_cast_import(self): self.assertUnimportEqual( source="""\ import typing if typing.TYPE_CHECKING: from PyQt5.QtWebKit import QWebHistory HistoryType = typing.cast('QWebHistory', None) """, expected_names=[ Name(lineno=2, name="typing.TYPE_CHECKING"), Name(lineno=5, name="HistoryType"), Name(lineno=5, name="QWebHistory"), Name(lineno=5, name="typing.cast"), ], expected_imports=[ Import( lineno=1, column=1, name="typing", package="typing", ), ImportFrom( lineno=3, column=1, name="QWebHistory", package="PyQt5.QtWebKit", star=False, suggestions=[], ), ], )
def test_union_import(self): source = ( "import typing\n" "if typing.TYPE_CHECKING:\n" " from PyQt5.QtWebEngineWidgets import QWebEngineHistory\n" " from PyQt5.QtWebKit import QWebHistory\n" "\n" "HistoryType = typing.Union['QWebEngineHistory', 'QWebHistory']\n" "\n") expected_names = [ Name(lineno=2, name="typing.TYPE_CHECKING"), Name(lineno=6, name="HistoryType"), Name(lineno=6, name="QWebEngineHistory"), Name(lineno=6, name="QWebHistory"), Name(lineno=6, name="typing.Union"), ] expected_imports = [ Import(lineno=1, column=1, name="typing"), ImportFrom( lineno=3, column=1, name="QWebEngineHistory", star=False, suggestions=[], ), ImportFrom( lineno=4, column=1, name="QWebHistory", star=False, suggestions=[], ), ] self.assertUnimportEqual(source, expected_names, expected_imports)
def test_two_multi_duplicate_one_used(self): source = ( "import t\n" "from l import t\n" "from x import y, z, t\n" "from i import t, ii\n" "print(t)\n" ) expected_unused_imports = [ Import( lineno=1, column=1, name="t", ), ImportFrom( lineno=2, column=1, name="t", star=False, suggestions=[] ), ImportFrom( lineno=3, column=1, name="y", star=False, suggestions=[] ), ImportFrom( lineno=3, column=2, name="z", star=False, suggestions=[] ), ImportFrom( lineno=3, column=3, name="t", star=False, suggestions=[] ), ImportFrom( lineno=4, column=2, name="ii", star=False, suggestions=[] ), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_as_import_all_unused_all_cases(self): source = ( "from x import y as z\n" "import x\n" "from t import s as ss\n" "from f import a as c, l as k, i as ii\n" "from fo import (bar, i, x as z)\n" "import le as x\n" ) expected_unused_imports = [ ImportFrom( lineno=1, column=1, name="z", star=False, suggestions=[] ), Import( lineno=2, column=1, name="x", ), ImportFrom( lineno=3, column=1, name="ss", star=False, suggestions=[] ), ImportFrom( lineno=4, column=1, name="c", star=False, suggestions=[] ), ImportFrom( lineno=4, column=2, name="k", star=False, suggestions=[] ), ImportFrom( lineno=4, column=3, name="ii", star=False, suggestions=[] ), ImportFrom( lineno=5, column=1, name="bar", star=False, suggestions=[] ), ImportFrom( lineno=5, column=2, name="i", star=False, suggestions=[] ), ImportFrom( lineno=5, column=3, name="z", star=False, suggestions=[] ), Import( lineno=6, column=1, name="x", ), ] self.assertUnimportEqual(source, expected_unused_imports)
def refactor(path: Path) -> str: source = utils.read(path)[0] with Analyzer(source=source) as analyzer: return refactor_string( source=analyzer.source, unused_imports=list(Import.get_unused_imports()), )
def test_unknown_module_unused(self): source = ("import x.y\n" "import d.f.a.s\n" "CURRENT_DIR = x.y('.').parent\n") expected_unused_imports = [ Import(lineno=2, module=None, name="d.f.a.s"), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_two_multi_duplicate_one_used(self): self.assertSourceAfterScanningEqualToExpected( """\ import t from l import t from x import y, z, t from i import t, ii print(t) """, [ Import( lineno=1, column=1, name="t", package="t", ), ImportFrom( lineno=2, column=1, name="t", package="l", star=False, suggestions=[], ), ImportFrom( lineno=3, column=1, name="y", package="x", star=False, suggestions=[], ), ImportFrom( lineno=3, column=2, name="z", package="x", star=False, suggestions=[], ), ImportFrom( lineno=3, column=3, name="t", package="x", star=False, suggestions=[], ), ImportFrom( lineno=4, column=2, name="ii", package="i", star=False, suggestions=[], ), ], )
def test_import_after_usage(self): self.assertSourceAfterScanningEqualToExpected( """\ def function(): print(os) import os """, [Import(lineno=3, column=1, name="os", package="os")], )
def visit_Import(self, node: ast.Import) -> None: if self.skip_import(node): return for column, alias in enumerate(node.names): name = alias.asname or alias.name self.imports.append( Import( lineno=node.lineno, column=column + 1, name=name, package=alias.name, ))
def test_space_between(self): """https://github.com/hakancelik96/unimport/issues/146.""" self.assertUnimportEqual( source="""\ import math import collections # noqa """, expected_imports=[ Import(lineno=1, column=1, name="math", package="math"), ], )
def test_skip_comment_multiline(self): self.assertUnimportEqual(source="""\ from package import ( module ) # unimport: skip """) self.assertUnimportEqual( source="""\ import x import y from package import ( module, module, module, ) # unimport: skip """, expected_imports=[ Import(lineno=1, column=1, name="x", package="x"), Import(lineno=2, column=1, name="y", package="y"), ], )
def test_two_used(self): source = ( "from x import y\n" "from x import y\n" "from t import x\n" "import re\n" "import ll\n" "import ll\n" "from c import e\n" "import e\n" "from pathlib import Path\n" "from pathlib import Path\n" "p = Path()\n" "print(ll)\n" ) expected_unused_imports = [ ImportFrom( lineno=1, column=1, name="y", star=False, suggestions=[] ), ImportFrom( lineno=2, column=1, name="y", star=False, suggestions=[] ), ImportFrom( lineno=3, column=1, name="x", star=False, suggestions=[] ), Import(lineno=4, column=1, name="re"), Import(lineno=5, column=1, name="ll"), ImportFrom( lineno=7, column=1, name="e", star=False, suggestions=[] ), Import( lineno=8, column=1, name="e", ), ImportFrom( lineno=9, column=1, name="Path", star=False, suggestions=[] ), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_same_line(self): source = ( "import x, x, yt\n" "import e, y, e\n" "from z import u, u\n" "from bb import c, d, c, c\n" "import ff, tt, ff, ff, tt\n" "from ee import (\n" " ll,\n" " el,\n" " ll,\n" " el,\n" " tl,\n" " tl,\n" ")\n" "import iss as si, si\n" "from gu import ug,\\\n" "ug" "\n" "x, e, u, c, ff, tt, ll, el, tl, si, ug, yt" ) expected_unused_imports = [ Import(lineno=1, column=1, name="x"), Import(lineno=2, column=1, name="e"), Import(lineno=2, column=2, name="y"), ImportFrom( lineno=3, column=1, name="u", star=False, suggestions=[] ), ImportFrom( lineno=4, column=1, name="c", star=False, suggestions=[] ), ImportFrom( lineno=4, column=2, name="d", star=False, suggestions=[] ), ImportFrom( lineno=4, column=3, name="c", star=False, suggestions=[] ), Import(lineno=5, column=1, name="ff"), Import(lineno=5, column=2, name="tt"), Import(lineno=5, column=3, name="ff"), ImportFrom( lineno=6, column=1, name="ll", star=False, suggestions=[] ), ImportFrom( lineno=6, column=2, name="el", star=False, suggestions=[] ), ImportFrom( lineno=6, column=5, name="tl", star=False, suggestions=[] ), Import(lineno=14, column=1, name="si"), ImportFrom( lineno=15, column=1, name="ug", star=False, suggestions=[] ), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_names_with_import(self): source = ("variable = 1\n" "import os\n" "class TestClass():\n" "\tdef test_function(self):\n" "\t\tpass\n" "def test_function():\n" "\tpass") self.assertUnimportEqual( source, expected_names=[Name(lineno=1, name="variable")], expected_imports=[Import(lineno=2, column=1, name="os")], )
def test_multi_duplicate(self): source = "from x import y, z, t\n" "import t\n" "from l import t\n" expected_unused_imports = [ ImportFrom(lineno=1, name="y", star=False, module=None, modules=[]), ImportFrom(lineno=1, name="z", star=False, module=None, modules=[]), ImportFrom(lineno=1, name="t", star=False, module=None, modules=[]), Import(lineno=2, name="t", module=None), ImportFrom(lineno=3, name="t", star=False, module=None, modules=[]), ] self.assertUnimportEqual(source, expected_unused_imports)
def visit_Import(self, node: ast.Import) -> None: if self.skip_import(node): return for column, alias in enumerate(node.names): name = alias.asname or alias.name if name in INITIAL_IMPORTS: name = name.split(".")[0] self.imports.append( Import( lineno=node.lineno, column=column + 1, name=name, )) self.import_names.append(name)
def test_normal_name_all_defined_top(self): self.assertUnimportEqual( source="""\ __all__ = ["x"] import x """, expected_names=[ Name(lineno=1, name="__all__"), Name(lineno=1, name="x", is_all=True), ], expected_imports=[ Import(lineno=2, column=1, name="x", package="x") ], )
def test_full_unused(self): source = ("from x import y\n" "from x import y\n" "from t import x\n" "import re\n" "import ll\n" "import ll\n" "from c import e\n" "import e\n") expected_unused_imports = [ ImportFrom(lineno=1, module=None, modules=[], name="y", star=False), ImportFrom(lineno=2, module=None, modules=[], name="y", star=False), ImportFrom(lineno=3, module=None, modules=[], name="x", star=False), Import(lineno=4, module=re, name="re"), Import(lineno=5, module=None, name="ll"), Import(lineno=6, module=None, name="ll"), ImportFrom(lineno=7, module=None, modules=[], name="e", star=False), Import(lineno=8, module=None, name="e"), ] self.assertUnimportEqual(source, expected_unused_imports)
def test_multi_duplicate(self): self.assertSourceAfterScanningEqualToExpected( """\ from x import y, z, t import t from l import t """, [ ImportFrom( lineno=1, column=1, name="y", package="x", star=False, suggestions=[], ), ImportFrom( lineno=1, column=2, name="z", package="x", star=False, suggestions=[], ), ImportFrom( lineno=1, column=3, name="t", package="x", star=False, suggestions=[], ), Import( lineno=2, column=1, name="t", package="t", ), ImportFrom( lineno=3, column=1, name="t", package="l", star=False, suggestions=[], ), ], )
def test_unknown_module_unused(self): self.assertSourceAfterScanningEqualToExpected( """\ import x.y import d.f.a.s CURRENT_DIR = x.y(".").parent """, [ Import( lineno=2, column=1, name="d.f.a.s", package="d.f.a.s", ), ], )
def test_names_with_import(self): self.assertUnimportEqual( source="""\ variable = 1 import os class TestClass(): def test_function(self): pass def test_function(): pass """, expected_names=[Name(lineno=1, name="variable")], expected_imports=[ Import(lineno=2, column=1, name="os", package="os") ], )
def test_union_import(self): self.assertUnimportEqual( source="""\ import typing if typing.TYPE_CHECKING: from PyQt5.QtWebEngineWidgets import QWebEngineHistory from PyQt5.QtWebKit import QWebHistory HistoryType = typing.Union['QWebEngineHistory', 'QWebHistory'] """, expected_names=[ Name(lineno=2, name="typing.TYPE_CHECKING"), Name(lineno=6, name="HistoryType"), Name(lineno=6, name="QWebEngineHistory"), Name(lineno=6, name="QWebHistory"), Name(lineno=6, name="typing.Union"), ], expected_imports=[ Import( lineno=1, column=1, name="typing", package="typing", ), ImportFrom( lineno=3, column=1, name="QWebEngineHistory", package="PyQt5.QtWebEngineWidgets", star=False, suggestions=[], ), ImportFrom( lineno=4, column=1, name="QWebHistory", package="PyQt5.QtWebKit", star=False, suggestions=[], ), ], )