Skip to content

Commit

Permalink
fix(move): Moves decorated function or class to other module
Browse files Browse the repository at this point in the history
  • Loading branch information
dryobates committed May 13, 2022
1 parent 6a86c2f commit b68d6f5
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
## New feature
- #464 Improve autoimport code to use a sqllite3 database, cache all available modules quickly, search for names and produce import statements, sort import statements.

## Bug fixes

- #419 Fix bug while moving decorated function (@dryobates)
- #439 Fix bug while moving decorated class (@dryobates)

# Release 1.0.0

Date: 2022-04-08
Expand Down
10 changes: 9 additions & 1 deletion rope/refactor/importutils/module_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@ def _first_import_line(self):
nodes[lineno], ast.ImportFrom
):
return nodes[lineno].lineno
lineno = self.pymodule.logical_lines.logical_line_in(nodes[lineno].lineno)[
first_line = get_first_decorator_or_function_start_line(nodes[lineno])
lineno = self.pymodule.logical_lines.logical_line_in(first_line)[
0
]
else:
Expand All @@ -288,6 +289,7 @@ def _first_import_line(self):
self.pymodule.lines.get_line, lineno - 1, 1, -1
)


def _get_import_name(self, import_stmt):
import_info = import_stmt.import_info
if hasattr(import_info, "module_name"):
Expand Down Expand Up @@ -340,6 +342,12 @@ def remove_pyname(self, pyname):
import_stmt.accept(visitor)


def get_first_decorator_or_function_start_line(node):
decorators = getattr(node, "decorator_list", [])
first_line = min([decorator.lineno for decorator in decorators] + [node.lineno])
return first_line


def _count_blank_lines(get_line, start, end, step=1):
count = 0
for idx in range(start, end, step):
Expand Down
7 changes: 4 additions & 3 deletions rope/refactor/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
)
from rope.base.change import ChangeSet, ChangeContents, MoveResource
from rope.refactor import importutils, rename, occurrences, sourceutils, functionutils
from rope.refactor.importutils.module_imports import get_first_decorator_or_function_start_line


def create_move(project, resource, offset=None):
Expand Down Expand Up @@ -435,9 +436,9 @@ def _get_moving_region(self):
start = lines.get_line_start(lineno)
end_line = logical_lines.logical_line_in(lineno)[1]
else:
scope = self.old_pyname.get_object().get_scope()
start = lines.get_line_start(scope.get_start())
end_line = scope.get_end()
node = self.old_pyname.get_object().ast_node
start = lines.get_line_start(get_first_decorator_or_function_start_line(node))
end_line = self.old_pyname.get_object().get_scope().get_end()

# Include comment lines before the definition
start_line = lines.get_line_number(start)
Expand Down
47 changes: 47 additions & 0 deletions ropetest/refactor/movetest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1257,3 +1257,50 @@ def f(): pass
self.project.do(mover.get_changes(self.mod1))
expected = "%s\n%s" % (code1, code2)
self.assertEqual(expected, self.mod1.read())

def test_moving_decorated_function(self):
self.mod1.write(
dedent("""\
def hello(func):
return func
@hello
def foo():
pass
""")
)
self._move(self.mod1, self.mod1.read().index("foo") + 1, self.mod2)
self.assertEqual("def hello(func):\n return func\n", self.mod1.read())
self.assertEqual(
dedent("""\
from mod1 import hello
@hello
def foo():
pass
"""),
self.mod2.read(),
)

def test_moving_decorated_class(self):
self.mod1.write(
dedent("""\
from dataclasses import dataclass
@dataclass
class AClass:
pass
""")
)
self._move(self.mod1, self.mod1.read().index("AClass") + 1, self.mod2)
self.assertEqual("", self.mod1.read())
self.assertEqual(
dedent("""\
from dataclasses import dataclass
@dataclass
class AClass:
pass
"""),
self.mod2.read(),
)

0 comments on commit b68d6f5

Please sign in to comment.