Move Refactoring
Relevant source files
The following files were used as context for generating this wiki page:
Move Refactoring is a core feature of the Rope library designed to safely relocate Python elements—including modules, global classes, functions, variables, and methods—within a project. The primary goal is to maintain code integrity by automatically updating references, managing imports, and adjusting code structures across the affected codebase.
The system employs a factory pattern to instantiate the appropriate refactoring object based on the type of element selected at a specific file offset. It leverages Rope's advanced static analysis to identify occurrences and calculate necessary changes, which are then packaged into ChangeSet objects for execution.
Sources: rope/refactor/move.py:1-40, README.rst:44-50
Architecture and Components
The Move Refactoring system is built around a centralized factory function and specialized classes that handle different refactoring scopes.
The Move Factory
The create_move() function serves as the entry point. It evaluates the provided resource and offset to determine if the user intends to move a module, a global entity, or a class method. If the location does not point to a supported element, it raises a RefactoringError.
Sources: rope/refactor/move.py:28-56
Core Refactoring Classes
Each class implements logic specific to its scope, primarily through the get_changes() method which returns a ChangeSet.
| Component | Description |
|---|---|
MoveMethod | Handles moving a method from one class to another via an attribute of the source class. |
MoveGlobal | Relocates global functions, classes, or variables to a different module. |
MoveModule | Moves files or packages to different directories, updating all import statements. |
_MoveTools | Helper class containing shared logic for renaming and import management. |
Sources: rope/refactor/move.py:59-65, rope/refactor/move.py:186, rope/refactor/move.py:316, rope/refactor/move.py:465
Logic and Data Flow
Global Element Relocation
Moving global elements involves three major steps: extracting the element from the source, inserting it into the destination, and updating all external references.
Key technical details include:
- Region Identification: For variables, logical lines are used. For functions/classes, decorators and the entire scope are included.
- Import Management: The
moving_code_with_importsfunction ensures that when code moves, its required imports follow it, and relative imports are converted to absolute imports. - Reference Updating: Occurrences in other modules are replaced with the new module path, often involving adding new
importorfrom ... importstatements.
Sources: rope/refactor/move.py:390-410, rope/refactor/move.py:530-560
Method Relocation
MoveMethod facilitates the "Move Method" refactoring pattern. It creates a new method in a destination class and refactors the old method to delegate calls to the new location.
- Host Transformation: If the method uses attributes of the original class (the "host"), the refactoring adds a
hostparameter to the new method and passesselffrom the old method. - Delegation: The old method body is replaced with
return self.dest_attr.new_name(args).
Sources: rope/refactor/move.py:108-115, rope/refactor/move.py:148-165
Resource Management and Changes
The refactoring process generates Change objects defined in the base system. These changes represent filesystem operations and file content modifications.
Multi-Project Support
Rope supports refactoring across multiple linked projects using multiproject.MultiProjectRefactoring. This ensures that if a module is moved in Project A, references in Project B (which depends on Project A) are also updated.
Sources: ropetest/refactor/multiprojecttest.py:46-68
Exceptional Conditions
The refactoring classes perform validation before generating changes:
- MoveMethod: Only normal methods can be moved; static or class methods may require different handling.
- MoveGlobal: Destination for non-modules cannot be folders; elements must be global (not nested).
- MoveModule: Non-package folders (folders without
__init__.py) cannot be moved using this refactoring.
Sources: rope/refactor/move.py:75, rope/refactor/move.py:270-280, rope/refactor/move.py:322, rope/refactor/extract.py:265-275
Move Refactoring in Rope is a complex operation that combines AST-based code analysis, precise range detection, and automated import management to ensure that code relocation remains a safe and predictable operation for Python developers.