[pitivi] undo: Rollback an action that raises an exception.
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] undo: Rollback an action that raises an exception.
- Date: Sat, 5 Aug 2017 20:29:43 +0000 (UTC)
commit c34184625ebe15ec8ea7afdb414bac1b43c85001
Author: Stefan Popa <stefanpopa2209 gmail com>
Date: Tue Aug 1 16:31:48 2017 +0300
undo: Rollback an action that raises an exception.
If an exception is raised in the self.app.action_log.started context,
catch it and rollback the started operation. Otherwise, the following
undoable operations will fail because the undo stack is not empty.
Reviewed-by: Alex Băluț <alexandru balut gmail com>
Differential Revision: https://phabricator.freedesktop.org/D1816
pitivi/undo/undo.py | 11 +++++++++--
tests/test_undo.py | 18 ++++++++++++++++++
2 files changed, 27 insertions(+), 2 deletions(-)
---
diff --git a/pitivi/undo/undo.py b/pitivi/undo/undo.py
index 721f5da..9c826a9 100644
--- a/pitivi/undo/undo.py
+++ b/pitivi/undo/undo.py
@@ -188,8 +188,15 @@ class UndoableActionLog(GObject.Object, Loggable):
def started(self, action_group_name, **kwargs):
"""Gets a context manager which commits the transaction at the end."""
self.begin(action_group_name, **kwargs)
- yield
- self.commit(action_group_name)
+ try:
+ yield
+ except:
+ self.warning("An exception occurred while recording a "
+ "high-level operation. Rolling back.")
+ self.rollback()
+ raise
+ else:
+ self.commit(action_group_name)
def begin(self, action_group_name, finalizing_action=None, toplevel=False):
"""Starts recording a high-level operation which later can be undone.
diff --git a/tests/test_undo.py b/tests/test_undo.py
index 9c5f386..408458a 100644
--- a/tests/test_undo.py
+++ b/tests/test_undo.py
@@ -388,6 +388,24 @@ class TestUndoableActionLog(TestCase):
self.log.begin("nested1")
self.log.begin("nested2", toplevel=False)
+ def test_failing_operation_rollback(self):
+ """Checks that failing operations are rolled back."""
+ action = mock.Mock(spec=UndoableAction)
+
+ class WatchingError(Exception):
+ pass
+
+ with self.assertRaises(WatchingError):
+ with self.log.started("failing_op"):
+ self.log.push(action)
+ raise WatchingError()
+
+ # Check the rollback happened
+ self.assertEqual(action.do.call_count, 0)
+ self.assertEqual(action.undo.call_count, 1)
+ # Check the undo and redo stacks are empty
+ self.assertEqual(len(self.log.undo_stacks), 0)
+ self.assertEqual(len(self.log.redo_stacks), 0)
class TestGObjectObserver(TestCase):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]