Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: tools/telemetry/third_party/rope/rope/base/history.py

Issue 1132103009: Example of refactoring using rope library. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/third_party/rope/rope/base/history.py
diff --git a/tools/telemetry/third_party/rope/rope/base/history.py b/tools/telemetry/third_party/rope/rope/base/history.py
new file mode 100644
index 0000000000000000000000000000000000000000..d3c523d310c41b42740253818ce4f94f04e6b988
--- /dev/null
+++ b/tools/telemetry/third_party/rope/rope/base/history.py
@@ -0,0 +1,235 @@
+from rope.base import exceptions, change, taskhandle
+
+
+class History(object):
+ """A class that holds project history"""
+
+ def __init__(self, project, maxundos=None):
+ self.project = project
+ self._undo_list = []
+ self._redo_list = []
+ self._maxundos = maxundos
+ self._load_history()
+ self.project.data_files.add_write_hook(self.write)
+ self.current_change = None
+
+ def _load_history(self):
+ if self.save:
+ result = self.project.data_files.read_data(
+ 'history', compress=self.compress, import_=True)
+ if result is not None:
+ to_change = change.DataToChange(self.project)
+ for data in result[0]:
+ self._undo_list.append(to_change(data))
+ for data in result[1]:
+ self._redo_list.append(to_change(data))
+
+ def do(self, changes, task_handle=taskhandle.NullTaskHandle()):
+ """Perform the change and add it to the `self.undo_list`
+
+ Note that uninteresting changes (changes to ignored files)
+ will not be appended to `self.undo_list`.
+
+ """
+ try:
+ self.current_change = changes
+ changes.do(change.create_job_set(task_handle, changes))
+ finally:
+ self.current_change = None
+ if self._is_change_interesting(changes):
+ self.undo_list.append(changes)
+ self._remove_extra_items()
+ del self.redo_list[:]
+
+ def _remove_extra_items(self):
+ if len(self.undo_list) > self.max_undos:
+ del self.undo_list[0:len(self.undo_list) - self.max_undos]
+
+ def _is_change_interesting(self, changes):
+ for resource in changes.get_changed_resources():
+ if not self.project.is_ignored(resource):
+ return True
+ return False
+
+ def undo(self, change=None, drop=False,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Redo done changes from the history
+
+ When `change` is `None`, the last done change will be undone.
+ If change is not `None` it should be an item from
+ `self.undo_list`; this change and all changes that depend on
+ it will be undone. In both cases the list of undone changes
+ will be returned.
+
+ If `drop` is `True`, the undone change will not be appended to
+ the redo list.
+
+ """
+ if not self._undo_list:
+ raise exceptions.HistoryError('Undo list is empty')
+ if change is None:
+ change = self.undo_list[-1]
+ dependencies = self._find_dependencies(self.undo_list, change)
+ self._move_front(self.undo_list, dependencies)
+ self._perform_undos(len(dependencies), task_handle)
+ result = self.redo_list[-len(dependencies):]
+ if drop:
+ del self.redo_list[-len(dependencies):]
+ return result
+
+ def redo(self, change=None, task_handle=taskhandle.NullTaskHandle()):
+ """Redo undone changes from the history
+
+ When `change` is `None`, the last undone change will be
+ redone. If change is not `None` it should be an item from
+ `self.redo_list`; this change and all changes that depend on
+ it will be redone. In both cases the list of redone changes
+ will be returned.
+
+ """
+ if not self.redo_list:
+ raise exceptions.HistoryError('Redo list is empty')
+ if change is None:
+ change = self.redo_list[-1]
+ dependencies = self._find_dependencies(self.redo_list, change)
+ self._move_front(self.redo_list, dependencies)
+ self._perform_redos(len(dependencies), task_handle)
+ return self.undo_list[-len(dependencies):]
+
+ def _move_front(self, change_list, changes):
+ for change in changes:
+ change_list.remove(change)
+ change_list.append(change)
+
+ def _find_dependencies(self, change_list, change):
+ index = change_list.index(change)
+ return _FindChangeDependencies(change_list[index:])()
+
+ def _perform_undos(self, count, task_handle):
+ for i in range(count):
+ self.current_change = self.undo_list[-1]
+ try:
+ job_set = change.create_job_set(task_handle,
+ self.current_change)
+ self.current_change.undo(job_set)
+ finally:
+ self.current_change = None
+ self.redo_list.append(self.undo_list.pop())
+
+ def _perform_redos(self, count, task_handle):
+ for i in range(count):
+ self.current_change = self.redo_list[-1]
+ try:
+ job_set = change.create_job_set(task_handle,
+ self.current_change)
+ self.current_change.do(job_set)
+ finally:
+ self.current_change = None
+ self.undo_list.append(self.redo_list.pop())
+
+ def contents_before_current_change(self, file):
+ if self.current_change is None:
+ return None
+ result = self._search_for_change_contents([self.current_change], file)
+ if result is not None:
+ return result
+ if file.exists() and not file.is_folder():
+ return file.read()
+ else:
+ return None
+
+ def _search_for_change_contents(self, change_list, file):
+ for change_ in reversed(change_list):
+ if isinstance(change_, change.ChangeSet):
+ result = self._search_for_change_contents(change_.changes,
+ file)
+ if result is not None:
+ return result
+ if isinstance(change_, change.ChangeContents) and \
+ change_.resource == file:
+ return change_.old_contents
+
+ def write(self):
+ if self.save:
+ data = []
+ to_data = change.ChangeToData()
+ self._remove_extra_items()
+ data.append([to_data(change_) for change_ in self.undo_list])
+ data.append([to_data(change_) for change_ in self.redo_list])
+ self.project.data_files.write_data('history', data,
+ compress=self.compress)
+
+ def get_file_undo_list(self, resource):
+ result = []
+ for change in self.undo_list:
+ if resource in change.get_changed_resources():
+ result.append(change)
+ return result
+
+ def __str__(self):
+ return 'History holds %s changes in memory' % \
+ (len(self.undo_list) + len(self.redo_list))
+
+ undo_list = property(lambda self: self._undo_list)
+ redo_list = property(lambda self: self._redo_list)
+
+ @property
+ def tobe_undone(self):
+ """The last done change if available, `None` otherwise"""
+ if self.undo_list:
+ return self.undo_list[-1]
+
+ @property
+ def tobe_redone(self):
+ """The last undone change if available, `None` otherwise"""
+ if self.redo_list:
+ return self.redo_list[-1]
+
+ @property
+ def max_undos(self):
+ if self._maxundos is None:
+ return self.project.prefs.get('max_history_items', 100)
+ else:
+ return self._maxundos
+
+ @property
+ def save(self):
+ return self.project.prefs.get('save_history', False)
+
+ @property
+ def compress(self):
+ return self.project.prefs.get('compress_history', False)
+
+ def clear(self):
+ """Forget all undo and redo information"""
+ del self.undo_list[:]
+ del self.redo_list[:]
+
+
+class _FindChangeDependencies(object):
+
+ def __init__(self, change_list):
+ self.change = change_list[0]
+ self.change_list = change_list
+ self.changed_resources = set(self.change.get_changed_resources())
+
+ def __call__(self):
+ result = [self.change]
+ for change in self.change_list[1:]:
+ if self._depends_on(change, result):
+ result.append(change)
+ self.changed_resources.update(change.get_changed_resources())
+ return result
+
+ def _depends_on(self, changes, result):
+ for resource in changes.get_changed_resources():
+ if resource is None:
+ continue
+ if resource in self.changed_resources:
+ return True
+ for changed in self.changed_resources:
+ if resource.is_folder() and resource.contains(changed):
+ return True
+ if changed.is_folder() and changed.contains(resource):
+ return True
+ return False
« no previous file with comments | « tools/telemetry/third_party/rope/rope/base/fscommands.py ('k') | tools/telemetry/third_party/rope/rope/base/libutils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698