A comprehensive Python refactoring library providing powerful and safe code transformations, analysis, and IDE integration capabilities.
—
System for representing, combining, and applying code changes safely. Enables previewing modifications before applying them and supports undo operations through project history.
Changes represent modifications to be made to the project, providing a safe way to preview and apply code transformations.
class Change:
"""
Base class for representing code changes.
"""
def do(self):
"""
Apply the change to the project.
This method should not be called directly - use project.do() instead.
"""
def get_description(self):
"""
Get human-readable description of the change.
Returns:
str: Description of what this change does
"""
class ChangeSet:
"""
Collection of multiple changes to be applied together.
"""
def __init__(self, description=""):
"""
Create a new change set.
Parameters:
- description (str): Description of the change set
"""
def add_change(self, change):
"""
Add a change to the set.
Parameters:
- change (Change): Change to add to the set
"""
def do(self):
"""Apply all changes in the set."""
def get_description(self):
"""Get description of all changes in the set."""Modifications to file contents including text replacement and formatting changes.
class ChangeContents(Change):
"""
Change the contents of a file.
Parameters:
- resource (Resource): File to modify
- new_contents (str): New file contents
- old_contents (str, optional): Expected current contents for validation
"""
def __init__(self, resource, new_contents, old_contents=None): ...
class ChangeContentsContent(Change):
"""
Change specific content within a file using string replacement.
Parameters:
- resource (Resource): File to modify
- old_content (str): Content to replace
- new_content (str): Replacement content
- offset (int, optional): Starting offset for change
"""
def __init__(self, resource, old_content, new_content, offset=None): ...Operations for creating, moving, and removing files and folders.
class CreateResource(Change):
"""
Create a new file or folder.
Parameters:
- project (Project): Project instance
- path (str): Path for new resource
"""
def __init__(self, project, path): ...
class CreateFile(CreateResource):
"""
Create a new file with optional initial content.
Parameters:
- project (Project): Project instance
- path (str): File path relative to project root
- contents (str, optional): Initial file contents
"""
def __init__(self, project, path, contents=""): ...
class CreateFolder(CreateResource):
"""
Create a new folder.
Parameters:
- project (Project): Project instance
- path (str): Folder path relative to project root
"""
def __init__(self, project, path): ...
class RemoveResource(Change):
"""
Remove a file or folder.
Parameters:
- project (Project): Project instance
- path (str): Path of resource to remove
"""
def __init__(self, project, path): ...
class MoveResource(Change):
"""
Move or rename a file or folder.
Parameters:
- project (Project): Project instance
- path (str): Current resource path
- new_path (str): New resource path
"""
def __init__(self, project, path, new_path): ...Progress monitoring and cancellation support for long-running operations.
class BaseTaskHandle:
"""Abstract base class for task monitoring."""
def stop(self):
"""Request task cancellation."""
def is_stopped(self):
"""
Check if task has been cancelled.
Returns:
bool: True if task should stop
"""
def is_finished(self):
"""
Check if task has completed.
Returns:
bool: True if task is finished
"""
class TaskHandle(BaseTaskHandle):
"""
Concrete task handle for monitoring refactoring progress.
Parameters:
- name (str): Task name for display
- cancel (callable, optional): Cancellation callback
"""
def __init__(self, name, cancel=None): ...
class BaseJobSet:
"""Abstract base class for managing multiple jobs."""
def create_job(self, name, count=None):
"""
Create a new job within the set.
Parameters:
- name (str): Job name
- count (int, optional): Expected number of work units
Returns:
Job instance for progress tracking
"""
class JobSet(BaseJobSet):
"""
Concrete job set for managing multiple parallel operations.
Parameters:
- task_handle (TaskHandle): Parent task handle
- count (int): Number of expected jobs
"""
def __init__(self, task_handle, count): ...
class NullTaskHandle(BaseTaskHandle):
"""No-op task handle that does nothing."""
pass
class NullJobSet(BaseJobSet):
"""No-op job set that does nothing."""
passDEFAULT_TASK_HANDLE = NullTaskHandle()
"""Default task handle instance for operations without progress monitoring."""Project history tracking for undo/redo functionality.
class History:
"""
Project change history for undo/redo operations.
"""
def do(self, changes):
"""
Execute changes and add to history.
Parameters:
- changes (Change or ChangeSet): Changes to execute and record
"""
def undo(self):
"""
Undo the last set of changes.
Returns:
ChangeSet: Changes that were undone
"""
def redo(self):
"""
Redo previously undone changes.
Returns:
ChangeSet: Changes that were redone
"""
def get_description(self):
"""Get description of current history state."""
class ChangeStack:
"""
Stack-based change management for contrib modules.
"""
def push(self, changes):
"""
Add changes to the stack.
Parameters:
- changes (Change or ChangeSet): Changes to add
"""
def pop(self):
"""
Remove and return top changes from stack.
Returns:
Change or ChangeSet: Top changes from stack
"""
def top(self):
"""
Get top changes without removing them.
Returns:
Change or ChangeSet: Top changes from stack
"""
def is_empty(self):
"""Check if stack is empty."""from rope.base.project import Project
from rope.base.change import ChangeContents, ChangeSet, CreateFile
project = Project('/path/to/project')
try:
# Create individual changes
myfile = project.get_resource('mymodule.py')
# Change file contents
new_content = "# Modified content\nprint('Hello, World!')\n"
content_change = ChangeContents(myfile, new_content)
# Create a new file
new_file_change = CreateFile(project, 'newmodule.py', '# New module\n')
# Combine changes into a change set
changes = ChangeSet("Update project files")
changes.add_change(content_change)
changes.add_change(new_file_change)
# Preview changes
print(f"About to apply: {changes.get_description()}")
# Apply all changes
project.do(changes)
finally:
project.close()from rope.base.project import Project
from rope.base.taskhandle import TaskHandle
from rope.refactor.rename import Rename
def my_cancel_callback():
print("Cancellation requested!")
return True
project = Project('/path/to/project')
try:
# Create task handle for monitoring
task_handle = TaskHandle("Rename refactoring", my_cancel_callback)
# Perform refactoring with progress monitoring
myfile = project.get_resource('mymodule.py')
renamer = Rename(project, myfile, 150)
changes = renamer.get_changes('new_name', task_handle=task_handle)
# Check if operation was cancelled
if not task_handle.is_stopped():
project.do(changes, task_handle)
print("Refactoring completed")
else:
print("Refactoring cancelled")
finally:
project.close()from rope.base.project import Project
from rope.base.change import CreateFolder, MoveResource, RemoveResource
project = Project('/path/to/project')
try:
# Create a new package structure
package_folder = CreateFolder(project, 'mypackage')
init_file = CreateFile(project, 'mypackage/__init__.py', '# Package init\n')
# Move existing module into package
move_module = MoveResource(project, 'oldmodule.py', 'mypackage/module.py')
# Remove obsolete file
remove_old = RemoveResource(project, 'obsolete.py')
# Apply all changes together
changes = ChangeSet("Reorganize project structure")
changes.add_change(package_folder)
changes.add_change(init_file)
changes.add_change(move_module)
changes.add_change(remove_old)
project.do(changes)
finally:
project.close()from rope.base.project import Project
from rope.base.change import ChangeContents
project = Project('/path/to/project')
try:
# Enable history tracking
history = project.history
# Make some changes
myfile = project.get_resource('mymodule.py')
original_content = myfile.read()
# First change
change1 = ChangeContents(myfile, original_content + "\n# First change")
history.do(change1)
# Second change
current_content = myfile.read()
change2 = ChangeContents(myfile, current_content + "\n# Second change")
history.do(change2)
# Undo last change
undone = history.undo()
print(f"Undone: {undone.get_description()}")
# Redo the change
redone = history.redo()
print(f"Redone: {redone.get_description()}")
finally:
project.close()from rope.base.project import Project
from rope.base.change import ChangeContents
project = Project('/path/to/project')
try:
myfile = project.get_resource('mymodule.py')
original_content = myfile.read()
# Create change with content validation
new_content = "# New content\nprint('Hello')\n"
change = ChangeContents(
myfile,
new_content,
old_contents=original_content # Validate current content
)
try:
project.do(change)
print("Change applied successfully")
except Exception as e:
print(f"Change failed: {e}")
finally:
project.close()Install with Tessl CLI
npx tessl i tessl/pypi-rope