add layer add / remove events + tests

This commit is contained in:
Jakob Ketterl 2020-03-24 20:36:26 +01:00
parent 4b7ac0e299
commit 14634af83c
2 changed files with 100 additions and 4 deletions

View File

@ -40,6 +40,10 @@ class PropertyManager(ABC):
def __dict__(self): def __dict__(self):
pass pass
@abstractmethod
def keys(self):
pass
def collect(self, *props): def collect(self, *props):
return PropertyFilter(self, *props) return PropertyFilter(self, *props)
@ -95,6 +99,9 @@ class PropertyLayer(PropertyManager):
def __dict__(self): def __dict__(self):
return {k: v for k, v in self.properties.items()} return {k: v for k, v in self.properties.items()}
def keys(self):
return self.properties.keys()
class PropertyFilter(PropertyManager): class PropertyFilter(PropertyManager):
def __init__(self, pm: PropertyManager, *props: str): def __init__(self, pm: PropertyManager, *props: str):
@ -126,6 +133,9 @@ class PropertyFilter(PropertyManager):
def __dict__(self): def __dict__(self):
return {k: v for k, v in self.pm.__dict__().items() if k in self.props} return {k: v for k, v in self.pm.__dict__().items() if k in self.props}
def keys(self):
return [k for k in self.pm.keys() if k in self.props]
class PropertyStack(PropertyManager): class PropertyStack(PropertyManager):
def __init__(self): def __init__(self):
@ -136,6 +146,10 @@ class PropertyStack(PropertyManager):
""" """
highest priority = 0 highest priority = 0
""" """
for key in pm.keys():
if key not in self or self[key] != pm[key]:
self._fireCallbacks(key, pm[key])
self.layers.append({"priority": priority, "props": pm}) self.layers.append({"priority": priority, "props": pm})
def eventClosure(name, value): def eventClosure(name, value):
@ -152,6 +166,12 @@ class PropertyStack(PropertyManager):
for layer in self.layers: for layer in self.layers:
if layer["props"] == pm: if layer["props"] == pm:
self.layers.remove(layer) self.layers.remove(layer)
for key in pm.keys():
if key in self:
if self[key] != pm[key]:
self._fireCallbacks(key, self[key])
else:
self._fireCallbacks(key, None)
def _getTopLayer(self, item): def _getTopLayer(self, item):
layers = [la["props"] for la in sorted(self.layers, key=lambda l: l["priority"])] layers = [la["props"] for la in sorted(self.layers, key=lambda l: l["priority"])]
@ -159,6 +179,7 @@ class PropertyStack(PropertyManager):
if item in m: if item in m:
return m return m
# return top layer by default # return top layer by default
if layers:
return layers[0] return layers[0]
def __getitem__(self, item): def __getitem__(self, item):
@ -171,8 +192,12 @@ class PropertyStack(PropertyManager):
def __contains__(self, item): def __contains__(self, item):
layer = self._getTopLayer(item) layer = self._getTopLayer(item)
if layer:
return layer.__contains__(item) return layer.__contains__(item)
return False
def __dict__(self): def __dict__(self):
keys = [key for l in self.layers for key in l["props"].__dict__().keys()] return {k: self.__getitem__(k) for k in self.keys()}
return {k: self.__getitem__(k) for k in keys}
def keys(self):
return set([key for l in self.layers for key in l["props"].keys()])

View File

@ -65,3 +65,74 @@ class PropertyStackTest(TestCase):
mock.method.assert_not_called() mock.method.assert_not_called()
high_layer["testkey"] = "modified high value" high_layer["testkey"] = "modified high value"
mock.method.assert_called_once_with("testkey", "modified high value") mock.method.assert_called_once_with("testkey", "modified high value")
def testPropertyEventOnLayerAdd(self):
low_layer = PropertyLayer()
low_layer["testkey"] = "low value"
stack = PropertyStack()
stack.addLayer(1, low_layer)
mock = Mock()
stack.wireProperty("testkey", mock.method)
mock.reset_mock()
high_layer = PropertyLayer()
high_layer["testkey"] = "high value"
stack.addLayer(0, high_layer)
mock.method.assert_called_once_with("high value")
def testNoEventOnExistingValue(self):
low_layer = PropertyLayer()
low_layer["testkey"] = "same value"
stack = PropertyStack()
stack.addLayer(1, low_layer)
mock = Mock()
stack.wireProperty("testkey", mock.method)
mock.reset_mock()
high_layer = PropertyLayer()
high_layer["testkey"] = "same value"
stack.addLayer(0, high_layer)
mock.method.assert_not_called()
def testEventOnLayerWithNewProperty(self):
low_layer = PropertyLayer()
low_layer["existingkey"] = "existing value"
stack = PropertyStack()
stack.addLayer(1, low_layer)
mock = Mock()
stack.wireProperty("newkey", mock.method)
high_layer = PropertyLayer()
high_layer["newkey"] = "new value"
stack.addLayer(0, high_layer)
mock.method.assert_called_once_with("new value")
def testEventOnLayerRemoval(self):
low_layer = PropertyLayer()
high_layer = PropertyLayer()
stack = PropertyStack()
stack.addLayer(1, low_layer)
stack.addLayer(0, high_layer)
low_layer["testkey"] = "low value"
high_layer["testkey"] = "high value"
mock = Mock()
stack.wireProperty("testkey", mock.method)
mock.method.assert_called_once_with("high value")
mock.reset_mock()
stack.removeLayer(high_layer)
mock.method.assert_called_once_with("low value")
def testNoneOnKeyRemoval(self):
low_layer = PropertyLayer()
high_layer = PropertyLayer()
stack = PropertyStack()
stack.addLayer(1, low_layer)
stack.addLayer(0, high_layer)
low_layer["testkey"] = "low value"
high_layer["testkey"] = "high value"
high_layer["unique key"] = "unique value"
mock = Mock()
stack.wireProperty("unique key", mock.method)
mock.method.assert_called_once_with("unique value")
mock.reset_mock()
stack.removeLayer(high_layer)
mock.method.assert_called_once_with(None)