diff --git a/CHANGELOG.md b/CHANGELOG.md index f4ef470fe..f4960c70d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # **Upcoming release** - #624 Implement `nonlocal` keyword (@lieryan) +- #696 Introduce the `prefer_global_from_imports` configuration (@nicoolas25) # Release 1.8.0 diff --git a/docs/default_config.py b/docs/default_config.py index 3543b07f1..f18d27657 100644 --- a/docs/default_config.py +++ b/docs/default_config.py @@ -112,6 +112,12 @@ def set_prefs(prefs): # # prefs["prefer_module_from_imports"] = False + # If `True`, rope will insert new name imports as + # `from import ` by default. + # + # prefs["prefer_global_from_imports"] = False + + # If `True`, rope will transform a comma list of imports into # multiple separate import statements when organizing # imports. diff --git a/rope/base/prefs.py b/rope/base/prefs.py index 9d4fd4a43..c97a0dfa2 100644 --- a/rope/base/prefs.py +++ b/rope/base/prefs.py @@ -143,7 +143,14 @@ class Prefs: prefer_module_from_imports: bool = field( default=False, description=dedent(""" - If `True`, rope will insert new module imports as `from import `by default. + If `True`, rope will insert new module imports as `from import ` by default. + """), + ) + + prefer_global_from_imports: bool = field( + default=False, + description=dedent(""" + If `True`, rope will insert new global imports as `from import ` by default. """), ) diff --git a/rope/refactor/importutils/__init__.py b/rope/refactor/importutils/__init__.py index e13276eb1..a872a6cbd 100644 --- a/rope/refactor/importutils/__init__.py +++ b/rope/refactor/importutils/__init__.py @@ -305,19 +305,23 @@ def add_import(project, pymodule, module_name, name=None): # from mod import name if name is not None: from_import = FromImport(module_name, 0, [(name, None)]) + if project.prefs.get("prefer_global_from_imports"): + selected_import = from_import names.append(name) candidates.append(from_import) + # from pkg import mod if "." in module_name: pkg, mod = module_name.rsplit(".", 1) from_import = FromImport(pkg, 0, [(mod, None)]) - if project.prefs.get("prefer_module_from_imports"): + if project.prefs.get("prefer_module_from_imports") and not selected_import: selected_import = from_import candidates.append(from_import) if name: names.append(mod + "." + name) else: names.append(mod) + # import mod normal_import = NormalImport([(module_name, None)]) if name: diff --git a/ropetest/refactor/movetest.py b/ropetest/refactor/movetest.py index 508069aa0..f38c144e2 100644 --- a/ropetest/refactor/movetest.py +++ b/ropetest/refactor/movetest.py @@ -177,6 +177,52 @@ def a_function(): self.mod3.read(), ) + def test_adding_imports_prefer_from_global(self): + self.project.prefs["prefer_global_from_imports"] = True + self.mod1.write(dedent("""\ + class AClass(object): + pass + def a_function(): + pass + """)) + self.mod3.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + mod1.a_function()""")) + # Move to mod4 which is in a different package + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod4) + self.assertEqual( + dedent("""\ + import mod1 + from pkg.mod4 import AClass + a_var = AClass() + mod1.a_function()"""), + self.mod3.read(), + ) + + def test_adding_imports_noprefer_from_global(self): + self.project.prefs["prefer_global_from_imports"] = False + self.mod1.write(dedent("""\ + class AClass(object): + pass + def a_function(): + pass + """)) + self.mod3.write(dedent("""\ + import mod1 + a_var = mod1.AClass() + mod1.a_function()""")) + # Move to mod4 which is in a different package + self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod4) + self.assertEqual( + dedent("""\ + import mod1 + import pkg.mod4 + a_var = pkg.mod4.AClass() + mod1.a_function()"""), + self.mod3.read(), + ) + def test_adding_imports_prefer_from_module(self): self.project.prefs["prefer_module_from_imports"] = True self.mod1.write(dedent("""\