From 62bbe40890600f2bed334c052e3be49ac70922fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hakan=20=C3=87elik?= Date: Fri, 1 Jan 2021 20:48:36 +0300 Subject: [PATCH] Fix #127 --- docs/CHANGELOG.md | 4 ++++ tests/test_refactor.py | 12 ------------ tests/test_unused_import.py | 15 +++++++++++++++ unimport/constants.py | 18 ------------------ unimport/scan.py | 2 -- unimport/statement.py | 30 +++++++++++++++--------------- unimport/utils.py | 4 ++-- 7 files changed, 36 insertions(+), 49 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 402eebce..956f2582 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## [Unreleased] - /././ + +- [Fix by @hakancelik96 #127](https://github.com/hakancelik96/unimport/pull/161) + ## [0.7.0] - 26/December/2020 - [%15 performance increase & remove show-error flag by @hakancelik96](https://github.com/hakancelik96/unimport/pull/159) diff --git a/tests/test_refactor.py b/tests/test_refactor.py index e06d13fe..30836b8e 100644 --- a/tests/test_refactor.py +++ b/tests/test_refactor.py @@ -254,18 +254,6 @@ def test_get_star_imp_none(self): """, ) - def test_initial_imports(self): - from unimport.constants import INITIAL_IMPORTS - - actions = [ - (f"import {imp_name}\n{imp_name.split('.')[0]}\n") - for imp_name in INITIAL_IMPORTS - ] - self.assertListEqual( - actions, - [self.refactor(action) for action in actions], - ) - class TestDuplicateUnusedRefactor(RefactorTestCase): def test_full_unused(self): diff --git a/tests/test_unused_import.py b/tests/test_unused_import.py index 3179ebf1..abc79353 100644 --- a/tests/test_unused_import.py +++ b/tests/test_unused_import.py @@ -25,6 +25,8 @@ def assertSourceAfterScanningEqualToExpected( class TestBuiltin(UnusedTestCase): + # https://github.com/hakancelik96/unimport/issues/45 + def test_ConnectionError(self): self.assertSourceAfterScanningEqualToExpected( """\ @@ -1187,3 +1189,16 @@ def x(t=x):pass ), ], ) + + +class TestDealingImplicitImportsSubPackages(UnusedTestCase): + # https://github.com/hakancelik96/unimport/issues/127 + + def test(self): + self.assertSourceAfterScanningEqualToExpected( + """\ + import x.y + + x + """, + ) diff --git a/unimport/constants.py b/unimport/constants.py index 7f949471..e367d51b 100644 --- a/unimport/constants.py +++ b/unimport/constants.py @@ -11,7 +11,6 @@ "VERSION", "PY38_PLUS", "SUBSCRIPT_TYPE_VARIABLE", - "INITIAL_IMPORTS", "IGNORE_IMPORT_NAMES", "BUILTINS", "Function", @@ -85,23 +84,6 @@ } ) -INITIAL_IMPORTS = frozenset( - # https://docs.python.org/3/library/sys.html#sys.modules - # The first thing Python will do is look up the name of import in sys.modules. - # Initial modules are below. - { - "encodings.utf_8", - "encodings.aliases", - "encodings.latin_1", - "importlib._bootstrap", - "importlib.abc", - "importlib.machinery", - "importlib._bootstrap_external", - "importlib.util", - "os.path", - } -) - IGNORE_IMPORT_NAMES = frozenset({"__all__", "__doc__", "__name__"}) BUILTINS = frozenset(dir(builtins)) diff --git a/unimport/scan.py b/unimport/scan.py index b9cb6c88..3691ef21 100644 --- a/unimport/scan.py +++ b/unimport/scan.py @@ -77,8 +77,6 @@ def visit_Import(self, node: ast.Import) -> None: return for column, alias in enumerate(node.names): name = alias.asname or alias.name - if name in C.INITIAL_IMPORTS: - name = name.split(".")[0] self.imports.append( Import( lineno=node.lineno, diff --git a/unimport/statement.py b/unimport/statement.py index 8755e5aa..1d74384a 100644 --- a/unimport/statement.py +++ b/unimport/statement.py @@ -13,6 +13,9 @@ class Import(NamedTuple): def __len__(self) -> int: return operator.length_hint(self.name.split(".")) + def is_match_sub_packages(self, name_name) -> bool: + return self.name.split(".")[0] == name_name + class ImportFrom(NamedTuple): lineno: int @@ -25,6 +28,9 @@ class ImportFrom(NamedTuple): def __len__(self) -> int: return operator.length_hint(self.name.split(".")) + def is_match_sub_packages(self, name_name): + return False + class Name(NamedTuple): lineno: int @@ -36,20 +42,14 @@ def is_attribute(self): return "." in self.name def match(self, imp: Union[Import, ImportFrom]) -> bool: - if self.is_attribute: - return self.__attribute_match(imp) - else: - return self.__name_match(imp) - - def __attribute_match(self, imp: Union[Import, ImportFrom]) -> bool: - """if the name is a attribute.""" - match = ".".join(self.name.split(".")[: len(imp)]) == imp.name - return imp.lineno < self.lineno and match - - def __name_match(self, imp: Union[Import, ImportFrom]) -> bool: - """if the name is a normal name.""" - match = self.name == imp.name if self.is_all: - return match + return self.name == imp.name + elif self.is_attribute: + return imp.lineno < self.lineno and ( + ".".join(self.name.split(".")[: len(imp)]) == imp.name + or imp.is_match_sub_packages(self.name) + ) else: - return imp.lineno < self.lineno and match + return (imp.lineno < self.lineno) and ( + self.name == imp.name or imp.is_match_sub_packages(self.name) + ) diff --git a/unimport/utils.py b/unimport/utils.py index 4f327fb3..b7324be9 100644 --- a/unimport/utils.py +++ b/unimport/utils.py @@ -3,8 +3,8 @@ import difflib import functools import importlib -import importlib.machinery # unimport: skip -import importlib.util # unimport: skip +import importlib.machinery +import importlib.util import re import tokenize from distutils.util import strtobool