MoveModule creates new top-level imports

Offen
#731 5 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Maintainer antworten meist innerhalb von 7 Tagen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
42/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Veraltet
Tech-Stack
python
Bereich
tooling

Rechercherichtung

The extra top-level import comes from rope/refactor/move.py, around the lines the reporter links (roughly 594-596 and 769-773). Start by running the reproducer in the issue, which moves lazy.py into prefix/ while utils.py imports it inside a function, and check where the import is added to the module header. Done means the function-local import is rewritten in place and no new top-level import appears, with the existing move tests still passing.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

bug

Describe the bug

When MoveModule encounters an import statement inside a function (thus, evaluated at some unknown point later and maybe never), and the import statement concerns the module being moved, the calculated changes include both a modification of the original import statement and an extraneous import statement at the top of the file. This changes the order of imports and, in sufficiently cursed code-bases, may even result in a circular import.

Basically, the issue is that MoveModule appears to consider imports to be side effect-free, which sometimes they aren't.

The extra import is being added here:
https://github.com/python-rope/rope/blob/25586a6c6d4eb339fdf09188c195d24b43970efb/rope/refactor/move.py#L594-L596
https://github.com/python-rope/rope/blob/25586a6c6d4eb339fdf09188c195d24b43970efb/rope/refactor/move.py#L769-L773

To Reproduce

Steps to reproduce the behavior:

  1. Code before refactoring:
# a.py
def use_b_later():
    import b

# b.py
import a
  1. Describe the refactoring you want to do

Rename (move) b into prefix.b.

  1. Expected code after refactoring:
# a.py
def use_b_later():
    import prefix.b

# b.py
import a
  1. Describe the error or unexpected result that you are getting
# a.py
import prefix.b

def use_b_later():
    import prefix.b

# b.py
import a

Reproducible example

$ python << EOF
import shutil
import tempfile
from contextlib import contextmanager
from os import walk
from pathlib import Path

from rope.base.project import Project
from rope.refactor.move import MoveModule


@contextmanager
def temp_tree():
    path = tempfile.mkdtemp()
    try:
        yield Path(path)
    finally:
        shutil.rmtree(path, ignore_errors=True)


with temp_tree() as root:

    (root / "utils.py").write_text(
        """
def use_lazy():
    import lazy"""
    )

    (root / "lazy.py").write_text(
        """
import utils"""
    )

    (root / "prefix").mkdir()
    (root / "prefix" / "__init__.py").touch()

    project = Project(root)

    new_package = project.get_folder("prefix")
    lazy = project.get_module("lazy").get_resource()

    print(MoveModule(project, lazy).get_changes(new_package).get_description())
EOF
Moving module <lazy>:


--- a/lazy.py
+++ b/lazy.py
@@ -1,2 +1 @@
-
-import utils+import utils

--- a/utils.py
+++ b/utils.py
@@ -1,3 +1,3 @@
-
+import prefix.lazy
 def use_lazy():
-    import lazy+    import prefix.lazy
rename from lazy.py
rename to prefix/lazy.py

Editor information (please complete the following information):

  • Project Python version: 3.11
  • Rope Python version: 3.11
  • Rope version: 1.11.0 (also checked 1.9.0)
  • Text editor/IDE and version: ...

Additional context

Context: trying to use Rope for some automation in https://github.com/SomeoneSerge/pkgs/blob/master/python-packages/by-name/pr/prefix-python-modules/prefix_python_modules.py

Vorherrschende Sprache
Python
Sterne
2.2k
Forks
197
Ø Merge
2 T. 13 Std.
Gemergte PRs (30 T.)
5

Entwicklungsumgebung

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus python-rope/rope

Alle Issues in python-rope/rope

Ähnliche Issues

Weitere Issues zu Python

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.