A comprehensive Python refactoring library providing powerful and safe code transformations, analysis, and IDE integration capabilities.
—
Exception hierarchy for handling various error conditions during code analysis and refactoring operations. Rope provides specific exception types for different failure scenarios to enable appropriate error handling and user feedback.
All rope exceptions inherit from the base RopeError class, providing a consistent error handling interface.
class RopeError(Exception):
"""
Base exception class for all rope errors.
All rope-specific exceptions inherit from this class.
"""
passErrors that occur during refactoring operations due to code structure or safety constraints.
class RefactoringError(RopeError):
"""
General refactoring error for operations that cannot be completed safely.
Raised when a refactoring violates safety constraints or encounters
unsupported code patterns.
"""
pass
class InterruptedTaskError(RopeError):
"""
Raised when a refactoring task is cancelled or interrupted.
Can occur when using TaskHandle to monitor long-running operations.
"""
passErrors related to file system operations and resource management.
class ResourceNotFoundError(RopeError):
"""
Raised when attempting to access a resource that doesn't exist.
Common when using project.get_resource() with invalid paths.
"""
passErrors related to Python module loading and import resolution.
class ModuleNotFoundError(RopeError):
"""
Raised when a Python module cannot be found or loaded.
Occurs during module resolution in project.get_module() operations.
"""
pass
class AttributeNotFoundError(RopeError):
"""
Raised when attempting to access a non-existent attribute.
Can occur during code analysis and refactoring operations.
"""
pass
class NameNotFoundError(RopeError):
"""
Raised when name resolution fails during code analysis.
Indicates that a referenced identifier cannot be resolved.
"""
passErrors related to code syntax and identifier validation.
class BadIdentifierError(RopeError):
"""
Raised when an invalid identifier is provided for refactoring.
Common in rename operations with non-Python identifiers.
"""
pass
class ModuleSyntaxError(RopeError):
"""
Raised when a Python module contains syntax errors.
Can occur during parsing and analysis operations.
"""
pass
class ModuleDecodeError(RopeError):
"""
Raised when a Python file cannot be decoded due to encoding issues.
Occurs when reading files with invalid or unsupported encodings.
"""
passErrors related to project history and state management.
class HistoryError(RopeError):
"""
Raised when history operations fail.
Can occur during undo/redo operations or history corruption.
"""
passfrom rope.base.project import Project
from rope.base.exceptions import RopeError, ResourceNotFoundError, RefactoringError
from rope.refactor.rename import Rename
project = Project('/path/to/project')
try:
# Attempt to get a resource
try:
myfile = project.get_resource('nonexistent.py')
except ResourceNotFoundError:
print("File not found, creating new file")
myfile = project.get_file('nonexistent.py')
myfile.write('# New file\n')
# Attempt refactoring with error handling
try:
renamer = Rename(project, myfile, 50)
old_name = renamer.get_old_name()
changes = renamer.get_changes('new_name')
project.do(changes)
print(f"Successfully renamed '{old_name}' to 'new_name'")
except RefactoringError as e:
print(f"Refactoring failed: {e}")
# Handle refactoring-specific errors
except BadIdentifierError as e:
print(f"Invalid identifier: {e}")
# Handle identifier validation errors
except RopeError as e:
print(f"Rope error occurred: {e}")
# Handle any rope-specific error
except Exception as e:
print(f"Unexpected error: {e}")
# Handle unexpected errors
finally:
project.close()from rope.base.project import Project
from rope.base.exceptions import ModuleNotFoundError, ModuleSyntaxError, ModuleDecodeError
project = Project('/path/to/project')
try:
# Handle various module loading errors
try:
module = project.get_module('mymodule')
print(f"Module loaded: {module}")
except ModuleNotFoundError:
print("Module not found in project or Python path")
# Try alternative module names or create module
except ModuleSyntaxError as e:
print(f"Module has syntax errors: {e}")
# Report syntax issues to user
except ModuleDecodeError as e:
print(f"Cannot decode module file: {e}")
# Handle encoding issues
finally:
project.close()from rope.base.project import Project
from rope.base.taskhandle import TaskHandle
from rope.base.exceptions import InterruptedTaskError
from rope.refactor.rename import Rename
def cancel_callback():
# Custom cancellation logic
return user_requested_cancel()
project = Project('/path/to/project')
try:
# Create task handle with cancellation support
task_handle = TaskHandle("Rename operation", cancel_callback)
try:
myfile = project.get_resource('mymodule.py')
renamer = Rename(project, myfile, 100)
changes = renamer.get_changes('new_name', task_handle=task_handle)
project.do(changes, task_handle)
print("Refactoring completed successfully")
except InterruptedTaskError:
print("Operation was cancelled by user")
# Clean up partial changes if necessary
finally:
project.close()from rope.base.project import Project
from rope.base.exceptions import *
from rope.refactor.extract import ExtractMethod
def safe_refactor(project_path, file_path, start_offset, end_offset, method_name):
"""
Safely perform extract method refactoring with comprehensive error handling.
"""
project = None
try:
project = Project(project_path)
# Resource access with error handling
try:
resource = project.get_resource(file_path)
except ResourceNotFoundError:
return {"error": f"File not found: {file_path}"}
# Refactoring with error handling
try:
extractor = ExtractMethod(project, resource, start_offset, end_offset)
changes = extractor.get_changes(method_name)
# Validate changes before applying
description = changes.get_description()
print(f"About to apply: {description}")
project.do(changes)
return {"success": f"Extracted method '{method_name}'"}
except RefactoringError as e:
return {"error": f"Refactoring failed: {e}"}
except BadIdentifierError as e:
return {"error": f"Invalid method name '{method_name}': {e}"}
except InterruptedTaskError:
return {"error": "Operation was cancelled"}
except ModuleSyntaxError as e:
return {"error": f"Syntax error in file: {e}"}
except RopeError as e:
return {"error": f"Rope error: {e}"}
except Exception as e:
return {"error": f"Unexpected error: {e}"}
finally:
if project:
project.close()
# Usage
result = safe_refactor(
"/path/to/project",
"mymodule.py",
200, 350,
"extracted_method"
)
if "error" in result:
print(f"Error: {result['error']}")
else:
print(f"Success: {result['success']}")from rope.base.project import Project
from rope.base.exceptions import *
def robust_rename(project_path, file_path, offset, new_name, max_retries=3):
"""
Perform rename with automatic retry and error recovery.
"""
project = Project(project_path)
try:
resource = project.get_resource(file_path)
for attempt in range(max_retries + 1):
try:
from rope.refactor.rename import Rename
renamer = Rename(project, resource, offset)
# Validate before proceeding
try:
old_name = renamer.get_old_name()
print(f"Attempt {attempt + 1}: Renaming '{old_name}' to '{new_name}'")
except AttributeNotFoundError:
print("No identifier found at offset")
return False
changes = renamer.get_changes(new_name)
project.do(changes)
print("Rename successful")
return True
except BadIdentifierError as e:
print(f"Invalid identifier on attempt {attempt + 1}: {e}")
if attempt == max_retries:
print("All attempts failed - invalid identifier")
return False
# Could try with modified identifier
except RefactoringError as e:
print(f"Refactoring error on attempt {attempt + 1}: {e}")
if attempt == max_retries:
print("All attempts failed - refactoring error")
return False
# Could try with different parameters
except InterruptedTaskError:
print("Operation cancelled")
return False
except ResourceNotFoundError:
print(f"File not found: {file_path}")
return False
finally:
project.close()
return FalseInstall with Tessl CLI
npx tessl i tessl/pypi-rope