Game Over

A Revertible Python dictionary

Here’s a Python dictionary-like class that supports undo/redo and transactions:

View source.

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!