-
-
Save justvanrossum/a873310e9c530c3a2f61d83518e5a475 to your computer and use it in GitHub Desktop.
Tests for undoManager.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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