MoveModule creates new top-level imports

Ouverte
#731 5 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 7 jours

Personne n'a encore pris cette issue.

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
42/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
À l'abandon
Stack technique
python
Domaine
tooling

Piste de recherche

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.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

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

Langage dominant
Python
Étoiles
2.2k
Forks
197
Merge moyen
2 j 13 h
PR mergées (30 j)
5

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de python-rope/rope

Toutes les issues de python-rope/rope

Issues similaires

Plus d'issues Python

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.