Skip to content

Instantly share code, notes, and snippets.

@justvanrossum
Last active December 19, 2018 15:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justvanrossum/a873310e9c530c3a2f61d83518e5a475 to your computer and use it in GitHub Desktop.
Save justvanrossum/a873310e9c530c3a2f61d83518e5a475 to your computer and use it in GitHub Desktop.
Tests for undoManager.py
# tests for https://gist.github.com/justvanrossum/1df375f3f784af47fab370270092f835
from collections.abc import Mapping, Sequence
import pytest
from undoManager import *
def test_module_docsting_example():
model = [1, 2, 3, {"a": 123}]
um = UndoManager()
proxy = um.setRootObject(model)
# Modifications have to done within a change set context:
with um.changeSet(title="replace list item"):
proxy[1] = 2000
assert model[1] == 2000
um.undo()
assert model[1] == 2
um.redo()
assert model[1] == 2000
with um.changeSet(title="replace nested dict item"):
proxy[3]["a"] = 456
assert model[3]["a"] == 456
um.undo()
assert model[3]["a"] == 123
def test_collections_abc():
o = UndoSequenceProxy(None, None, None)
assert isinstance(o, Sequence)
o = UndoMappingProxy(None, None, None)
assert isinstance(o, Mapping)
def test_UndoProxy_dispatch():
assert UndoProxy(1, None) == 1
assert UndoProxy(1.2, None) == 1.2
assert UndoProxy("1.2", None) == "1.2"
assert type(UndoProxy([], None)) == UndoSequenceProxy
assert type(UndoProxy({}, None)) == UndoMappingProxy
assert type(UndoProxy(_AttrContainer(), None)) == UndoAttributeProxy
def test_modify_without_changeSet():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with pytest.raises(UndoManagerError):
lp.append("foo")
assert "foo" not in l
def test_nested_changeSet():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="outer"):
with pytest.raises(UndoManagerError):
with um.changeSet(title="inner"):
pass
class _error_dict(dict):
def __setitem__(self, key, value):
raise ValueError("test")
def test_modify_error():
model = _error_dict()
um = UndoManager()
proxy = um.setRootObject(model)
with pytest.raises(ValueError):
with um.changeSet(title="error test"):
proxy["a"] = 12
assert um._currentChangeSet is None
assert um._currentInverseChangeSet is None
assert "a" not in model
# assert that we *didn't* record an undo change
assert len(um.undoStack) == 0
assert len(um.undoStack) == 0
def test_replacing_root():
um = UndoManager()
proxy = um.setRootObject({})
with pytest.raises(AssertionError):
proxy = um.setRootObject({})
def test_list_append():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
lp.append("a")
lp.append("b")
assert len(um.undoStack) == 1
assert len(um.redoStack) == 0
assert l == [0, 1, 2, 3, "a", "b"]
for a, b in zip(l, lp):
assert a == b
assert um.undoInfo() == {"title": "list test"}
assert um.redoInfo() is None
assert len(um.undoStack) == 1
assert len(um.redoStack) == 0
um.undo()
assert um.undoInfo() is None
assert um.redoInfo() == {"title": "list test"}
assert len(um.undoStack) == 0
assert len(um.redoStack) == 1
assert l == [0, 1, 2, 3]
um.redo()
assert l == [0, 1, 2, 3, "a", "b"]
with pytest.raises(UndoManagerError):
um.redo()
def test_list_insert():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
lp.insert(2, "a")
lp.insert(1, "b")
lp.insert(5, "c")
assert l == [0, "b", 1, "a", 2, "c", 3]
um.undo()
assert l == [0, 1, 2, 3]
um.redo()
assert l == [0, "b", 1, "a", 2, "c", 3]
def test_list_insert_double():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
lp.insert(2, "a")
lp.insert(2, "b")
assert l == [0, 1, "b", "a", 2, 3]
um.undo()
assert l == [0, 1, 2, 3]
um.redo()
assert l == [0, 1, "b", "a", 2, 3]
def test_list_remove():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
del lp[2]
assert l == [0, 1, 3]
um.undo()
assert l == [0, 1, 2, 3]
um.redo()
assert l == [0, 1, 3]
def test_list_remove_double():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
del lp[1]
del lp[1]
assert l == [0, 3]
um.undo()
assert l == [0, 1, 2, 3]
um.redo()
assert l == [0, 3]
def test_list_replace():
l = [0, 1, 2, 3]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
lp[2] = "a"
assert l == [0, 1, "a", 3]
um.undo()
assert l == [0, 1, 2, 3]
um.redo()
assert l == [0, 1, "a", 3]
um.undo()
assert l == [0, 1, 2, 3]
def test_list_replace2():
l = ["a", "b", "c"]
um = UndoManager()
lp = um.setRootObject(l)
with um.changeSet(title="list test"):
lp[1] = "B"
assert lp[1] == l[1] == "B"
um.undo()
assert l == ["a", "b", "c"]
um.redo()
assert l == ["a", "B", "c"]
def test_dictionary():
d = {}
um = UndoManager()
dp = um.setRootObject(d)
with um.changeSet(title="dict test"):
dp["a"] = 12
assert d == {"a": 12}
assert d["a"] == dp["a"]
with um.changeSet(title="dict test 2"):
dp["a"] = 1200
assert d == {"a": 1200}
with um.changeSet(title="dict test 3"):
dp["b"] = 24
assert d == {"a": 1200, "b": 24}
um.undo()
assert d == {"a": 1200}
um.undo()
assert d == {"a": 12}
um.undo()
assert d == {}
um.redo()
um.redo()
um.redo()
assert d == {"a": 1200, "b": 24}
um.undo()
with um.changeSet(title="dict test 4"):
dp["c"] = 48
#assert d == {"a": 1200, "c": 24}
assert d == {"a": 1200, "c": 48}
with pytest.raises(UndoManagerError):
um.redo()
with um.changeSet(title="dict test 5"):
del dp["a"]
assert d == {"c": 48}
um.undo()
um.undo()
assert d == {"a": 1200}
def test_dictionary_multiple():
d = {}
um = UndoManager()
dp = um.setRootObject(d)
with um.changeSet(title="dict test"):
dp["a"] = 12
with um.changeSet(title="dict test multiple"):
dp["a"] = 13
dp["a"] = 14
um.undo()
assert d["a"] == 12
um.redo()
assert d["a"] == 14
def test_object():
o = _AttrContainer()
um = UndoManager()
op = um.setRootObject(o)
assert o.__dict__ == {}
with um.changeSet(title="object test"):
op.foo = 12
assert o.__dict__ == {"foo": 12}
assert op.foo == o.foo
um.undo()
assert o.__dict__ == {}
um.redo()
assert o.__dict__ == {"foo": 12}
with um.changeSet(title="object test 2"):
del op.foo
assert o.__dict__ == {}
um.undo()
assert o.__dict__ == {"foo": 12}
with pytest.raises(UndoManagerError):
op.bar = 123
def test_callable():
o = _AttrContainer()
um = UndoManager()
op = um.setRootObject(o)
assert op.someMethod(3) == 5
class _AttrContainer:
def someMethod(self, x):
return x + 2
def __repr__(self):
return "%s(%s)" % (self.__class__.__name__,
", ".join("%s=%r" % (k, v) for k, v in self.__dict__.items()))
def test_generic_hasItem():
d = {"a": 1}
o = _AttrContainer()
o.foo = 1
assert hasItem(d, "a")
assert hasItem(o, "foo")
assert not hasItem(d, "b")
assert not hasItem(o, "bar")
def test_generic_getItem():
d = {"a": 1}
l = [1]
o = _AttrContainer()
o.foo = 1
assert getItem(d, "a") == 1
assert getItem(l, 0) == 1
assert getItem(o, "foo") == 1
def test_generic_addItem():
d = {"a": 1}
l = [1]
o = _AttrContainer()
o.foo = 1
addItem(d, "b", 2)
addItem(l, 1, 2)
addItem(o, "bar", 2)
assert getItem(d, "b") == 2
assert getItem(l, 1) == 2
assert getItem(o, "bar") == 2
with pytest.raises(AssertionError):
addItem(d, "b", 2)
with pytest.raises(AssertionError):
addItem(o, "bar", 2)
def test_generic_replaceItem():
d = {"a": 1}
l = [1]
o = _AttrContainer()
o.foo = 1
replaceItem(d, "a", 2)
replaceItem(l, 0, 2)
replaceItem(o, "foo", 2)
assert getItem(d, "a") == 2
assert getItem(l, 0) == 2
assert getItem(o, "foo") == 2
with pytest.raises(AssertionError):
replaceItem(d, "b", 2)
with pytest.raises(AssertionError):
replaceItem(o, "bar", 2)
def test_generic_removeItem():
d = {"a": 1}
l = [1]
o = _AttrContainer()
o.foo = 1
removeItem(d, "a")
removeItem(l, 0)
removeItem(o, "foo")
assert not hasItem(d, "a")
assert len(l) == 0
assert not hasItem(o, "foo")
def test_getDeepItem():
o = _AttrContainer()
o.foo = "foo"
d = {"a": [1, 2, 3, {"b": 4, "c": ["a", "b", "c"]}, o]}
assert getDeepItem(d, ("a", 1)) == 2
assert getDeepItem(d, ("a", 2)) == 3
assert getDeepItem(d, ("a", 3, "b")) == 4
assert getDeepItem(d, ("a", 3, "c", 1)) == "b"
assert getDeepItem(d, ("a", 4)) == o
assert getDeepItem(d, ("a", 4, "foo")) == "foo"
with pytest.raises(AttributeError):
getDeepItem(d, ("a", 2, "b"))
with pytest.raises(IndexError):
getDeepItem(d, ("a", 5))
def test_addDeepItem():
o = _AttrContainer()
d = {"a": [1, 2, 3, {"b": 4, "c": ["a", "b", "c", o]}]}
addDeepItem(d, ("b",), "B")
assert getDeepItem(d, ("b",)) == "B"
addDeepItem(d, ("a", 0), "C")
assert d == {"a": ["C", 1, 2, 3, {"b": 4, "c": ["a", "b", "c", o]}], "b": "B"}
addDeepItem(d, ("a", 4, "c", 4), "Q")
assert d == {"a": ["C", 1, 2, 3, {"b": 4, "c": ["a", "b", "c", o, "Q"]}], "b": "B"}
addDeepItem(d, ("a", 4, "c", 3, "foo"), "QQQ")
with pytest.raises(AssertionError):
addDeepItem(d, ("a", 4, "c", 3, "foo"), "QQQ")
assert getDeepItem(d, ("a", 4, "c", 3, "foo")) == "QQQ"
assert o.foo == "QQQ"
def test_replaceDeepItem():
o = _AttrContainer()
o.foo = 1
d = {"a": [1, 2, 3, {"b": 4, "c": ["a", "b", "c"], "d": o}]}
replaceDeepItem(d, ("a", 1), 222)
assert d == {"a": [1, 222, 3, {"b": 4, "c": ["a", "b", "c"], "d": o}]}
replaceDeepItem(d, ("a", 3, "d", "foo"), 222)
assert o.foo == 222
with pytest.raises(AssertionError):
replaceDeepItem(d, ("b"), 333)
with pytest.raises(AssertionError):
replaceDeepItem(d, ("a", 3, "d", "bar"), 222)
def test_removeDeepItem():
o = _AttrContainer()
o.foo = 1
d = {"a": [1, 2, 3, {"b": 4, "c": ["a", "b", "c"], "d": o}]}
removeDeepItem(d, ("a", 1))
assert d == {"a": [1, 3, {"b": 4, "c": ["a", "b", "c"], "d": o}]}
removeDeepItem(d, ("a", 2, "c", 1))
assert d == {"a": [1, 3, {"b": 4, "c": ["a", "c"], "d": o}]}
removeDeepItem(d, ("a", 2, "c"))
assert d == {"a": [1, 3, {"b": 4, "d": o}]}
assert hasattr(o, "foo")
removeDeepItem(d, ("a", 2, "d", "foo"))
assert not hasattr(o, "foo")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment