A Revertible Python dictionary
Here's a Python dictionary-like class that supports undo/redo and transactions:
I wrote it while trying to solve back-button support in Nitro apps, but ended up taking a different, simpler approach, which I'll describe in a later blog post.
The dict lets you do this:
d = RevertibleDict()
assert 'x' not in d
d['x'] = 42
assert d['x'] == 42
d.undo()
assert 'x' not in d
d.redo()
assert d['x'] == 42
This works for nested keys, too, e.g. d['x', 'y'] = 42
, since Python treats 'x', 'y'
as the tuple ('x', 'y')
.
Setting individual entries is not useful in itself. Typically, you'd want to change multiple entries and revert a whole batch of changes.
Enter transactions:
d = RevertibleDict()
with d:
d['x'] = 42
d['y'] = 43
d['z'] = 44
assert d['x'] == 42
assert d['y'] == 43
assert d['z'] == 44
assert d['x'] == 42
assert d['y'] == 43
assert d['z'] == 44
d.undo()
assert 'x' not in d
assert 'y' not in d
assert 'z' not in d
d.redo()
assert d['x'] == 42
assert d['y'] == 43
assert d['z'] == 44
The transaction is committed when exiting the with
context. If an exception occurs, the changes are rolled back.
The entire implementation is ~125 lines of code, and includes a generic undo/redo history manager, if you want to author different kinds of revertible data structures.
Happy hacking!