send property changes in bulk to global subscribers

This commit is contained in:
Jakob Ketterl 2020-12-30 17:14:06 +01:00
parent eb34c45145
commit 2c3146314b
4 changed files with 32 additions and 31 deletions

View File

@ -71,15 +71,22 @@ class PropertyManager(ABC):
pass
return self
def _fireCallbacks(self, name, value):
def _fireCallbacks(self, changes):
if not changes:
return
for c in self.subscribers:
try:
if c.getName() is None:
c.call(name, value)
elif c.getName() == name:
c.call(value)
except Exception as e:
logger.exception(e)
c.call(changes)
except Exception:
logger.exception("exception while firing changes")
for name in changes:
for c in self.subscribers:
try:
if c.getName() == name:
c.call(changes[name])
except Exception:
logger.exception("exception while firing changes")
class PropertyLayer(PropertyManager):
@ -97,7 +104,7 @@ class PropertyLayer(PropertyManager):
if name in self.properties and self.properties[name] == value:
return
self.properties[name] = value
self._fireCallbacks(name, value)
self._fireCallbacks({name: value})
def __dict__(self):
return {k: v for k, v in self.properties.items()}
@ -116,10 +123,9 @@ class PropertyFilter(PropertyManager):
self.props = props
self.pm.wire(self.receiveEvent)
def receiveEvent(self, name, value):
if name not in self.props:
return
self._fireCallbacks(name, value)
def receiveEvent(self, changes):
changesToForward = {name: value for name, value in changes.items() if name in self.props}
self._fireCallbacks(changesToForward)
def __getitem__(self, item):
if item not in self.props:
@ -157,7 +163,7 @@ class PropertyStack(PropertyManager):
"""
highest priority = 0
"""
self._fireChanges(self._addLayer(priority, pm))
self._fireCallbacks(self._addLayer(priority, pm))
def _addLayer(self, priority: int, pm: PropertyManager):
changes = {}
@ -165,8 +171,8 @@ class PropertyStack(PropertyManager):
if key not in self or self[key] != pm[key]:
changes[key] = pm[key]
def eventClosure(name, value):
self.receiveEvent(pm, name, value)
def eventClosure(changes):
self.receiveEvent(pm, changes)
sub = pm.wire(eventClosure)
@ -177,7 +183,7 @@ class PropertyStack(PropertyManager):
def removeLayer(self, pm: PropertyManager):
for layer in self.layers:
if layer["props"] == pm:
self._fireChanges(self._removeLayer(layer))
self._fireCallbacks(self._removeLayer(layer))
def _removeLayer(self, layer):
layer["sub"].cancel()
@ -201,16 +207,11 @@ class PropertyStack(PropertyManager):
changes = {**changes, **self._addLayer(priority, pm)}
changes = {k: v for k, v in changes.items() if k not in originalState or originalState[k] != v}
self._fireChanges(changes)
self._fireCallbacks(changes)
def _fireChanges(self, changes):
for k, v in changes.items():
self._fireCallbacks(k, v)
def receiveEvent(self, layer, name, value):
if layer != self._getTopLayer(name):
return
self._fireCallbacks(name, value)
def receiveEvent(self, layer, changes):
changesToForward = {name: value for name, value in changes.items() if layer == self._getTopLayer(name)}
self._fireCallbacks(changesToForward)
def _getTopLayer(self, item):
layers = [la["props"] for la in sorted(self.layers, key=lambda l: l["priority"])]

View File

@ -11,7 +11,7 @@ class PropertyFilterTest(TestCase):
pf = PropertyFilter(pm, "testkey")
self.assertEqual(pf["testkey"], "testvalue")
def testMissesPropert(self):
def testMissesProperty(self):
pm = PropertyLayer()
pm["testkey"] = "testvalue"
pf = PropertyFilter(pm, "other_key")
@ -25,7 +25,7 @@ class PropertyFilterTest(TestCase):
mock = Mock()
pf.wire(mock.method)
pm["testkey"] = "testvalue"
mock.method.assert_called_once_with("testkey", "testvalue")
mock.method.assert_called_once_with({"testkey": "testvalue"})
def testForwardsPropertyEvent(self):
pm = PropertyLayer()

View File

@ -19,7 +19,7 @@ class PropertyLayerTest(TestCase):
mock = Mock()
pm.wire(mock.method)
pm["testkey"] = "after"
mock.method.assert_called_once_with("testkey", "after")
mock.method.assert_called_once_with({"testkey": "after"})
def testUnsubscribe(self):
pm = PropertyLayer()
@ -27,7 +27,7 @@ class PropertyLayerTest(TestCase):
mock = Mock()
sub = pm.wire(mock.method)
pm["testkey"] = "between"
mock.method.assert_called_once_with("testkey", "between")
mock.method.assert_called_once_with({"testkey": "between"})
mock.reset_mock()
pm.unwire(sub)

View File

@ -49,7 +49,7 @@ class PropertyStackTest(TestCase):
mock = Mock()
stack.wire(mock.method)
layer["testkey"] = "testvalue"
mock.method.assert_called_once_with("testkey", "testvalue")
mock.method.assert_called_once_with({"testkey": "testvalue"})
def testPropertyChangeEventPriority(self):
low_layer = PropertyLayer()
@ -64,7 +64,7 @@ class PropertyStackTest(TestCase):
low_layer["testkey"] = "modified low value"
mock.method.assert_not_called()
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()
@ -162,7 +162,7 @@ class PropertyStackTest(TestCase):
mock = Mock()
stack.wire(mock.method)
stack.removeLayer(layer)
mock.method.assert_called_once_with("testkey", None)
mock.method.assert_called_once_with({"testkey": None})
mock.reset_mock()
layer["testkey"] = "after"