From 7e5181afb0619faa85093e17e4191166474e0bd0 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Thu, 4 Apr 2024 16:48:49 +1100 Subject: [PATCH 1/4] Add ImportInfo.__repr__() --- rope/refactor/importutils/importinfo.py | 3 +++ ropetest/reprtest.py | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/rope/refactor/importutils/importinfo.py b/rope/refactor/importutils/importinfo.py index 283513c4a..640200c4c 100644 --- a/rope/refactor/importutils/importinfo.py +++ b/rope/refactor/importutils/importinfo.py @@ -73,6 +73,9 @@ def get_imported_names(self, context): primary.split(".")[0] for primary in self.get_imported_primaries(context) ] + def __repr__(self): + return f'<{self.__class__.__name__} "{self.get_import_statement()}">' + def get_import_statement(self): pass diff --git a/ropetest/reprtest.py b/ropetest/reprtest.py index 96954846c..3adbab789 100644 --- a/ropetest/reprtest.py +++ b/ropetest/reprtest.py @@ -10,6 +10,7 @@ from rope.contrib import findit from rope.contrib.autoimport import models from rope.refactor import occurrences +from rope.refactor.importutils import importinfo from ropetest import testutils @@ -165,3 +166,24 @@ def test_autoimport_models_finalquery(project, mod1): obj = models.Package.delete_by_package_name assert isinstance(obj, models.FinalQuery) assert repr(obj) == expected_repr + + +def test_repr_normal_import(project): + obj = importinfo.NormalImport([("abc", None), ("ghi", "jkl")]) + expected_repr = '' + assert isinstance(obj, importinfo.NormalImport) + assert repr(obj) == expected_repr + + +def test_repr_from_import(project): + obj = importinfo.FromImport("pkg1.pkg2", 0, [("abc", None), ("ghi", "jkl")]) + expected_repr = '' + assert isinstance(obj, importinfo.FromImport) + assert repr(obj) == expected_repr + + +def test_repr_from_import_with_level(project): + obj = importinfo.FromImport("pkg1.pkg2", 3, [("abc", None), ("ghi", "jkl")]) + expected_repr = '' + assert isinstance(obj, importinfo.FromImport) + assert repr(obj) == expected_repr From 7ac96d253afc6c5a02a32329679d1fa6bfe87e22 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Thu, 4 Apr 2024 23:04:59 +1100 Subject: [PATCH 2/4] Add type annotations to importinfo.py --- rope/refactor/importutils/importinfo.py | 45 +++++++++++++++++-------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/rope/refactor/importutils/importinfo.py b/rope/refactor/importutils/importinfo.py index 640200c4c..451a387e4 100644 --- a/rope/refactor/importutils/importinfo.py +++ b/rope/refactor/importutils/importinfo.py @@ -1,4 +1,5 @@ -from typing import List, Tuple +from abc import abstractmethod, ABC +from typing import List, Tuple, Optional, Protocol class ImportStatement: @@ -64,9 +65,11 @@ def accept(self, visitor): return visitor.dispatch(self) -class ImportInfo: - def get_imported_primaries(self, context): - pass +class ImportInfo(ABC): + names_and_aliases: List[Tuple[str, Optional[str]]] + + @abstractmethod + def get_imported_primaries(self, context) -> List[str]: ... def get_imported_names(self, context): return [ @@ -76,8 +79,8 @@ def get_imported_names(self, context): def __repr__(self): return f'<{self.__class__.__name__} "{self.get_import_statement()}">' - def get_import_statement(self): - pass + @abstractmethod + def get_import_statement(self) -> str: ... def is_empty(self): pass @@ -108,10 +111,13 @@ def get_empty_import(): class NormalImport(ImportInfo): - def __init__(self, names_and_aliases): + def __init__( + self, + names_and_aliases: List[Tuple[str, Optional[str]]], + ) -> None: self.names_and_aliases = names_and_aliases - def get_imported_primaries(self, context): + def get_imported_primaries(self, context) -> List[str]: result = [] for name, alias in self.names_and_aliases: if alias: @@ -120,7 +126,7 @@ def get_imported_primaries(self, context): result.append(name) return result - def get_import_statement(self): + def get_import_statement(self) -> str: result = "import " for name, alias in self.names_and_aliases: result += name @@ -134,12 +140,20 @@ def is_empty(self): class FromImport(ImportInfo): - def __init__(self, module_name, level, names_and_aliases): + module_name: str + level: int + + def __init__( + self, + module_name: str, + level: int, + names_and_aliases: List[Tuple[str, Optional[str]]], + ): self.module_name = module_name self.level = level self.names_and_aliases = names_and_aliases - def get_imported_primaries(self, context): + def get_imported_primaries(self, context) -> List[str]: if self.names_and_aliases[0][0] == "*": module = self.get_imported_module(context) return [name for name in module if not name.startswith("_")] @@ -176,7 +190,7 @@ def get_imported_module(self, context): self.module_name, context.folder, self.level ) - def get_import_statement(self): + def get_import_statement(self) -> str: result = "from " + "." * self.level + self.module_name + " import " for name, alias in self.names_and_aliases: result += name @@ -193,14 +207,17 @@ def is_star_import(self): class EmptyImport(ImportInfo): - names_and_aliases: List[Tuple[str, str]] = [] + names_and_aliases = [] def is_empty(self): return True - def get_imported_primaries(self, context): + def get_imported_primaries(self, context) -> List[str]: return [] + def get_import_statement(self) -> str: + raise NotImplementedError() + class ImportContext: def __init__(self, project, folder): From 1cc05a80faa3725720b47e266c0fe924b5952a88 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Thu, 4 Apr 2024 23:46:08 +1100 Subject: [PATCH 3/4] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ae3435ce..20b1e72ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # **Upcoming release** +- #787 Add type hints to importinfo.py and add repr to ImportInfo (@lieryan) - #786 Upgrade Actions used in Github Workflows (@lieryan) - #785 Refactoring movetest.py (@lieryan) From 3f89161a91757fadf33f432c56fcc488d6f1b289 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Thu, 4 Apr 2024 23:56:43 +1100 Subject: [PATCH 4/4] Add "raise NotImplementedError()" to coverage exclusion --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 8c17acd2b..f10067297 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,6 +87,7 @@ force-exclude = 'ropetest|rope/base/prefs.py' [tool.coverage.report] exclude_also = [ "if TYPE_CHECKING:", + "raise NotImplementedError()", ] [tool.isort]