Skip to content

Commit

Permalink
Merge pull request #548 from python-rope/lieryan-move-global-with-str…
Browse files Browse the repository at this point in the history
…ing-destination

Implement MoveGlobal using string as destination module names
  • Loading branch information
lieryan committed Dec 22, 2022
2 parents 86d8d90 + 211a005 commit 4293428
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- #607 Remove importing from legacy files with `.pickle` suffix
- #625 Remove support for deprecated ast nodes
- #616, #621 Remove `file` builtins
- #548 Implement MoveGlobal using string as destination module names

# Release 1.6.0

Expand Down
46 changes: 46 additions & 0 deletions docs/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,52 @@ consider we want to move ``attr`` to ``A``. We can do that by renaming
You can move the definition of ``attr`` manually.


Moving Global Classes/Functions/Variables
-----------------------------------------

You can move global classes/function/variables to another module by using the
Move refactoring on a global object:

For instance, in this refactoring, if you are moving ``twice()`` to
``pkg1.mod2``:

.. code-block:: python
# pkg1/mod1.py
def twice(a):
return a * 2
print(twice(4))
.. code-block:: python
# pkg1/mod3.py
import pkg1.mod1
pkg1.mod1.twice(13)
When asked for the destination module, put in ``pkg1.mod2``. Rope will update
all the imports.

.. code-block:: python
# pkg1/mod1.py
import pkg1.mod2
print(pkg1.mod2.twice(4))
.. code-block:: python
# pkg1/mod2.py
def twice(a):
return a * 2
.. code-block:: python
# pkg1/mod3.py
import pkg1.mod2
pkg1.mod2.twice(13)
Extract Method
--------------

Expand Down
3 changes: 2 additions & 1 deletion rope/base/project.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
import sys
import warnings
from typing import Optional

import rope.base.fscommands # Use full qualification for clarity.
from rope.base import (
Expand Down Expand Up @@ -141,7 +142,7 @@ def get_relative_module(self, name, folder, level):
raise ModuleNotFoundError("Module %s not found" % name)
return self.pycore.resource_to_pyobject(module)

def find_module(self, modname, folder=None):
def find_module(self, modname, folder=None) -> Optional[File]:
"""Returns a resource corresponding to the given module
returns None if it can not be found
Expand Down
31 changes: 30 additions & 1 deletion rope/refactor/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
based on inputs.
"""
from __future__ import annotations

import typing
from typing import Union

from rope.base import (
codeanalyze,
evaluate,
Expand All @@ -21,6 +26,13 @@
)


if typing.TYPE_CHECKING:
from rope.base import (
project,
resources,
)


def create_move(project, resource, offset=None):
"""A factory for creating Move objects
Expand Down Expand Up @@ -231,6 +243,8 @@ def _is_host_used(self):
class MoveGlobal:
"""For moving global function and classes"""

project: project.Project

def __init__(self, project, resource, offset):
self.project = project
this_pymodule = self.project.get_pymodule(resource)
Expand Down Expand Up @@ -299,8 +313,23 @@ def _is_variable(self, pyname):
return isinstance(pyname, pynames.AssignedName)

def get_changes(
self, dest, resources=None, task_handle=taskhandle.NullTaskHandle()
self,
dest: Union[None, str, resources.Resource],
resources=None,
task_handle=taskhandle.NullTaskHandle(),
):
"""Return the changes needed for this refactoring
Parameters:
- `dest`: the Resource or dotted moddule name of the move destination
- `resources` can be a list of `rope.base.resources.File` to
apply this refactoring on. If `None`, the restructuring
will be applied to all python files.
"""
if isinstance(dest, str):
dest = self.project.find_module(dest)
if resources is None:
resources = self.project.get_python_files()
if dest is None or not dest.exists():
Expand Down
12 changes: 12 additions & 0 deletions ropetest/refactor/movetest.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ def test_move_constant_2(self):
self.assertEqual("bar = 321\n", self.mod1.read())
self.assertEqual("foo = 123\n", self.mod2.read())

def test_move_target_is_module_name(self):
self.mod1.write("foo = 123\n")
self._move(self.mod1, self.mod1.read().index("foo") + 1, "mod2")
self.assertEqual("", self.mod1.read())
self.assertEqual("foo = 123\n", self.mod2.read())

def test_move_target_is_package_name(self):
self.mod1.write("foo = 123\n")
self._move(self.mod1, self.mod1.read().index("foo") + 1, "pkg.mod4")
self.assertEqual("", self.mod1.read())
self.assertEqual("foo = 123\n", self.mod4.read())

def test_move_constant_multiline(self):
self.mod1.write(dedent("""\
foo = (
Expand Down

0 comments on commit 4293428

Please sign in to comment.