0
# Change Management
1
2
System for representing, combining, and applying code changes safely. Enables previewing modifications before applying them and supports undo operations through project history.
3
4
## Capabilities
5
6
### Change Representation
7
8
Changes represent modifications to be made to the project, providing a safe way to preview and apply code transformations.
9
10
```python { .api }
11
class Change:
12
"""
13
Base class for representing code changes.
14
"""
15
16
def do(self):
17
"""
18
Apply the change to the project.
19
This method should not be called directly - use project.do() instead.
20
"""
21
22
def get_description(self):
23
"""
24
Get human-readable description of the change.
25
26
Returns:
27
str: Description of what this change does
28
"""
29
30
class ChangeSet:
31
"""
32
Collection of multiple changes to be applied together.
33
"""
34
35
def __init__(self, description=""):
36
"""
37
Create a new change set.
38
39
Parameters:
40
- description (str): Description of the change set
41
"""
42
43
def add_change(self, change):
44
"""
45
Add a change to the set.
46
47
Parameters:
48
- change (Change): Change to add to the set
49
"""
50
51
def do(self):
52
"""Apply all changes in the set."""
53
54
def get_description(self):
55
"""Get description of all changes in the set."""
56
```
57
58
### Content Changes
59
60
Modifications to file contents including text replacement and formatting changes.
61
62
```python { .api }
63
class ChangeContents(Change):
64
"""
65
Change the contents of a file.
66
67
Parameters:
68
- resource (Resource): File to modify
69
- new_contents (str): New file contents
70
- old_contents (str, optional): Expected current contents for validation
71
"""
72
def __init__(self, resource, new_contents, old_contents=None): ...
73
74
class ChangeContentsContent(Change):
75
"""
76
Change specific content within a file using string replacement.
77
78
Parameters:
79
- resource (Resource): File to modify
80
- old_content (str): Content to replace
81
- new_content (str): Replacement content
82
- offset (int, optional): Starting offset for change
83
"""
84
def __init__(self, resource, old_content, new_content, offset=None): ...
85
```
86
87
### Resource Changes
88
89
Operations for creating, moving, and removing files and folders.
90
91
```python { .api }
92
class CreateResource(Change):
93
"""
94
Create a new file or folder.
95
96
Parameters:
97
- project (Project): Project instance
98
- path (str): Path for new resource
99
"""
100
def __init__(self, project, path): ...
101
102
class CreateFile(CreateResource):
103
"""
104
Create a new file with optional initial content.
105
106
Parameters:
107
- project (Project): Project instance
108
- path (str): File path relative to project root
109
- contents (str, optional): Initial file contents
110
"""
111
def __init__(self, project, path, contents=""): ...
112
113
class CreateFolder(CreateResource):
114
"""
115
Create a new folder.
116
117
Parameters:
118
- project (Project): Project instance
119
- path (str): Folder path relative to project root
120
"""
121
def __init__(self, project, path): ...
122
123
class RemoveResource(Change):
124
"""
125
Remove a file or folder.
126
127
Parameters:
128
- project (Project): Project instance
129
- path (str): Path of resource to remove
130
"""
131
def __init__(self, project, path): ...
132
133
class MoveResource(Change):
134
"""
135
Move or rename a file or folder.
136
137
Parameters:
138
- project (Project): Project instance
139
- path (str): Current resource path
140
- new_path (str): New resource path
141
"""
142
def __init__(self, project, path, new_path): ...
143
```
144
145
### Task Handling
146
147
Progress monitoring and cancellation support for long-running operations.
148
149
```python { .api }
150
class BaseTaskHandle:
151
"""Abstract base class for task monitoring."""
152
153
def stop(self):
154
"""Request task cancellation."""
155
156
def is_stopped(self):
157
"""
158
Check if task has been cancelled.
159
160
Returns:
161
bool: True if task should stop
162
"""
163
164
def is_finished(self):
165
"""
166
Check if task has completed.
167
168
Returns:
169
bool: True if task is finished
170
"""
171
172
class TaskHandle(BaseTaskHandle):
173
"""
174
Concrete task handle for monitoring refactoring progress.
175
176
Parameters:
177
- name (str): Task name for display
178
- cancel (callable, optional): Cancellation callback
179
"""
180
def __init__(self, name, cancel=None): ...
181
182
class BaseJobSet:
183
"""Abstract base class for managing multiple jobs."""
184
185
def create_job(self, name, count=None):
186
"""
187
Create a new job within the set.
188
189
Parameters:
190
- name (str): Job name
191
- count (int, optional): Expected number of work units
192
193
Returns:
194
Job instance for progress tracking
195
"""
196
197
class JobSet(BaseJobSet):
198
"""
199
Concrete job set for managing multiple parallel operations.
200
201
Parameters:
202
- task_handle (TaskHandle): Parent task handle
203
- count (int): Number of expected jobs
204
"""
205
def __init__(self, task_handle, count): ...
206
207
class NullTaskHandle(BaseTaskHandle):
208
"""No-op task handle that does nothing."""
209
pass
210
211
class NullJobSet(BaseJobSet):
212
"""No-op job set that does nothing."""
213
pass
214
```
215
216
### Constants
217
218
```python { .api }
219
DEFAULT_TASK_HANDLE = NullTaskHandle()
220
"""Default task handle instance for operations without progress monitoring."""
221
```
222
223
### History Management
224
225
Project history tracking for undo/redo functionality.
226
227
```python { .api }
228
class History:
229
"""
230
Project change history for undo/redo operations.
231
"""
232
233
def do(self, changes):
234
"""
235
Execute changes and add to history.
236
237
Parameters:
238
- changes (Change or ChangeSet): Changes to execute and record
239
"""
240
241
def undo(self):
242
"""
243
Undo the last set of changes.
244
245
Returns:
246
ChangeSet: Changes that were undone
247
"""
248
249
def redo(self):
250
"""
251
Redo previously undone changes.
252
253
Returns:
254
ChangeSet: Changes that were redone
255
"""
256
257
def get_description(self):
258
"""Get description of current history state."""
259
260
class ChangeStack:
261
"""
262
Stack-based change management for contrib modules.
263
"""
264
265
def push(self, changes):
266
"""
267
Add changes to the stack.
268
269
Parameters:
270
- changes (Change or ChangeSet): Changes to add
271
"""
272
273
def pop(self):
274
"""
275
Remove and return top changes from stack.
276
277
Returns:
278
Change or ChangeSet: Top changes from stack
279
"""
280
281
def top(self):
282
"""
283
Get top changes without removing them.
284
285
Returns:
286
Change or ChangeSet: Top changes from stack
287
"""
288
289
def is_empty(self):
290
"""Check if stack is empty."""
291
```
292
293
## Usage Examples
294
295
### Basic Change Operations
296
297
```python
298
from rope.base.project import Project
299
from rope.base.change import ChangeContents, ChangeSet, CreateFile
300
301
project = Project('/path/to/project')
302
303
try:
304
# Create individual changes
305
myfile = project.get_resource('mymodule.py')
306
307
# Change file contents
308
new_content = "# Modified content\nprint('Hello, World!')\n"
309
content_change = ChangeContents(myfile, new_content)
310
311
# Create a new file
312
new_file_change = CreateFile(project, 'newmodule.py', '# New module\n')
313
314
# Combine changes into a change set
315
changes = ChangeSet("Update project files")
316
changes.add_change(content_change)
317
changes.add_change(new_file_change)
318
319
# Preview changes
320
print(f"About to apply: {changes.get_description()}")
321
322
# Apply all changes
323
project.do(changes)
324
325
finally:
326
project.close()
327
```
328
329
### Task Progress Monitoring
330
331
```python
332
from rope.base.project import Project
333
from rope.base.taskhandle import TaskHandle
334
from rope.refactor.rename import Rename
335
336
def my_cancel_callback():
337
print("Cancellation requested!")
338
return True
339
340
project = Project('/path/to/project')
341
342
try:
343
# Create task handle for monitoring
344
task_handle = TaskHandle("Rename refactoring", my_cancel_callback)
345
346
# Perform refactoring with progress monitoring
347
myfile = project.get_resource('mymodule.py')
348
renamer = Rename(project, myfile, 150)
349
changes = renamer.get_changes('new_name', task_handle=task_handle)
350
351
# Check if operation was cancelled
352
if not task_handle.is_stopped():
353
project.do(changes, task_handle)
354
print("Refactoring completed")
355
else:
356
print("Refactoring cancelled")
357
358
finally:
359
project.close()
360
```
361
362
### Resource Management Changes
363
364
```python
365
from rope.base.project import Project
366
from rope.base.change import CreateFolder, MoveResource, RemoveResource
367
368
project = Project('/path/to/project')
369
370
try:
371
# Create a new package structure
372
package_folder = CreateFolder(project, 'mypackage')
373
init_file = CreateFile(project, 'mypackage/__init__.py', '# Package init\n')
374
375
# Move existing module into package
376
move_module = MoveResource(project, 'oldmodule.py', 'mypackage/module.py')
377
378
# Remove obsolete file
379
remove_old = RemoveResource(project, 'obsolete.py')
380
381
# Apply all changes together
382
changes = ChangeSet("Reorganize project structure")
383
changes.add_change(package_folder)
384
changes.add_change(init_file)
385
changes.add_change(move_module)
386
changes.add_change(remove_old)
387
388
project.do(changes)
389
390
finally:
391
project.close()
392
```
393
394
### History and Undo Operations
395
396
```python
397
from rope.base.project import Project
398
from rope.base.change import ChangeContents
399
400
project = Project('/path/to/project')
401
402
try:
403
# Enable history tracking
404
history = project.history
405
406
# Make some changes
407
myfile = project.get_resource('mymodule.py')
408
original_content = myfile.read()
409
410
# First change
411
change1 = ChangeContents(myfile, original_content + "\n# First change")
412
history.do(change1)
413
414
# Second change
415
current_content = myfile.read()
416
change2 = ChangeContents(myfile, current_content + "\n# Second change")
417
history.do(change2)
418
419
# Undo last change
420
undone = history.undo()
421
print(f"Undone: {undone.get_description()}")
422
423
# Redo the change
424
redone = history.redo()
425
print(f"Redone: {redone.get_description()}")
426
427
finally:
428
project.close()
429
```
430
431
### Change Validation
432
433
```python
434
from rope.base.project import Project
435
from rope.base.change import ChangeContents
436
437
project = Project('/path/to/project')
438
439
try:
440
myfile = project.get_resource('mymodule.py')
441
original_content = myfile.read()
442
443
# Create change with content validation
444
new_content = "# New content\nprint('Hello')\n"
445
change = ChangeContents(
446
myfile,
447
new_content,
448
old_contents=original_content # Validate current content
449
)
450
451
try:
452
project.do(change)
453
print("Change applied successfully")
454
except Exception as e:
455
print(f"Change failed: {e}")
456
457
finally:
458
project.close()
459
```