add layer add / remove events + tests
This commit is contained in:
parent
4b7ac0e299
commit
14634af83c
@ -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()])
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user