send property changes in bulk to global subscribers
This commit is contained in:
parent
eb34c45145
commit
2c3146314b
@ -71,15 +71,22 @@ class PropertyManager(ABC):
|
|||||||
pass
|
pass
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def _fireCallbacks(self, name, value):
|
def _fireCallbacks(self, changes):
|
||||||
|
if not changes:
|
||||||
|
return
|
||||||
for c in self.subscribers:
|
for c in self.subscribers:
|
||||||
try:
|
try:
|
||||||
if c.getName() is None:
|
if c.getName() is None:
|
||||||
c.call(name, value)
|
c.call(changes)
|
||||||
elif c.getName() == name:
|
except Exception:
|
||||||
c.call(value)
|
logger.exception("exception while firing changes")
|
||||||
except Exception as e:
|
for name in changes:
|
||||||
logger.exception(e)
|
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):
|
class PropertyLayer(PropertyManager):
|
||||||
@ -97,7 +104,7 @@ class PropertyLayer(PropertyManager):
|
|||||||
if name in self.properties and self.properties[name] == value:
|
if name in self.properties and self.properties[name] == value:
|
||||||
return
|
return
|
||||||
self.properties[name] = value
|
self.properties[name] = value
|
||||||
self._fireCallbacks(name, value)
|
self._fireCallbacks({name: value})
|
||||||
|
|
||||||
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()}
|
||||||
@ -116,10 +123,9 @@ class PropertyFilter(PropertyManager):
|
|||||||
self.props = props
|
self.props = props
|
||||||
self.pm.wire(self.receiveEvent)
|
self.pm.wire(self.receiveEvent)
|
||||||
|
|
||||||
def receiveEvent(self, name, value):
|
def receiveEvent(self, changes):
|
||||||
if name not in self.props:
|
changesToForward = {name: value for name, value in changes.items() if name in self.props}
|
||||||
return
|
self._fireCallbacks(changesToForward)
|
||||||
self._fireCallbacks(name, value)
|
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def __getitem__(self, item):
|
||||||
if item not in self.props:
|
if item not in self.props:
|
||||||
@ -157,7 +163,7 @@ class PropertyStack(PropertyManager):
|
|||||||
"""
|
"""
|
||||||
highest priority = 0
|
highest priority = 0
|
||||||
"""
|
"""
|
||||||
self._fireChanges(self._addLayer(priority, pm))
|
self._fireCallbacks(self._addLayer(priority, pm))
|
||||||
|
|
||||||
def _addLayer(self, priority: int, pm: PropertyManager):
|
def _addLayer(self, priority: int, pm: PropertyManager):
|
||||||
changes = {}
|
changes = {}
|
||||||
@ -165,8 +171,8 @@ class PropertyStack(PropertyManager):
|
|||||||
if key not in self or self[key] != pm[key]:
|
if key not in self or self[key] != pm[key]:
|
||||||
changes[key] = pm[key]
|
changes[key] = pm[key]
|
||||||
|
|
||||||
def eventClosure(name, value):
|
def eventClosure(changes):
|
||||||
self.receiveEvent(pm, name, value)
|
self.receiveEvent(pm, changes)
|
||||||
|
|
||||||
sub = pm.wire(eventClosure)
|
sub = pm.wire(eventClosure)
|
||||||
|
|
||||||
@ -177,7 +183,7 @@ class PropertyStack(PropertyManager):
|
|||||||
def removeLayer(self, pm: PropertyManager):
|
def removeLayer(self, pm: PropertyManager):
|
||||||
for layer in self.layers:
|
for layer in self.layers:
|
||||||
if layer["props"] == pm:
|
if layer["props"] == pm:
|
||||||
self._fireChanges(self._removeLayer(layer))
|
self._fireCallbacks(self._removeLayer(layer))
|
||||||
|
|
||||||
def _removeLayer(self, layer):
|
def _removeLayer(self, layer):
|
||||||
layer["sub"].cancel()
|
layer["sub"].cancel()
|
||||||
@ -201,16 +207,11 @@ class PropertyStack(PropertyManager):
|
|||||||
changes = {**changes, **self._addLayer(priority, pm)}
|
changes = {**changes, **self._addLayer(priority, pm)}
|
||||||
changes = {k: v for k, v in changes.items() if k not in originalState or originalState[k] != v}
|
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):
|
def receiveEvent(self, layer, changes):
|
||||||
for k, v in changes.items():
|
changesToForward = {name: value for name, value in changes.items() if layer == self._getTopLayer(name)}
|
||||||
self._fireCallbacks(k, v)
|
self._fireCallbacks(changesToForward)
|
||||||
|
|
||||||
def receiveEvent(self, layer, name, value):
|
|
||||||
if layer != self._getTopLayer(name):
|
|
||||||
return
|
|
||||||
self._fireCallbacks(name, value)
|
|
||||||
|
|
||||||
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"])]
|
||||||
|
@ -11,7 +11,7 @@ class PropertyFilterTest(TestCase):
|
|||||||
pf = PropertyFilter(pm, "testkey")
|
pf = PropertyFilter(pm, "testkey")
|
||||||
self.assertEqual(pf["testkey"], "testvalue")
|
self.assertEqual(pf["testkey"], "testvalue")
|
||||||
|
|
||||||
def testMissesPropert(self):
|
def testMissesProperty(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
pm["testkey"] = "testvalue"
|
pm["testkey"] = "testvalue"
|
||||||
pf = PropertyFilter(pm, "other_key")
|
pf = PropertyFilter(pm, "other_key")
|
||||||
@ -25,7 +25,7 @@ class PropertyFilterTest(TestCase):
|
|||||||
mock = Mock()
|
mock = Mock()
|
||||||
pf.wire(mock.method)
|
pf.wire(mock.method)
|
||||||
pm["testkey"] = "testvalue"
|
pm["testkey"] = "testvalue"
|
||||||
mock.method.assert_called_once_with("testkey", "testvalue")
|
mock.method.assert_called_once_with({"testkey": "testvalue"})
|
||||||
|
|
||||||
def testForwardsPropertyEvent(self):
|
def testForwardsPropertyEvent(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
|
@ -19,7 +19,7 @@ class PropertyLayerTest(TestCase):
|
|||||||
mock = Mock()
|
mock = Mock()
|
||||||
pm.wire(mock.method)
|
pm.wire(mock.method)
|
||||||
pm["testkey"] = "after"
|
pm["testkey"] = "after"
|
||||||
mock.method.assert_called_once_with("testkey", "after")
|
mock.method.assert_called_once_with({"testkey": "after"})
|
||||||
|
|
||||||
def testUnsubscribe(self):
|
def testUnsubscribe(self):
|
||||||
pm = PropertyLayer()
|
pm = PropertyLayer()
|
||||||
@ -27,7 +27,7 @@ class PropertyLayerTest(TestCase):
|
|||||||
mock = Mock()
|
mock = Mock()
|
||||||
sub = pm.wire(mock.method)
|
sub = pm.wire(mock.method)
|
||||||
pm["testkey"] = "between"
|
pm["testkey"] = "between"
|
||||||
mock.method.assert_called_once_with("testkey", "between")
|
mock.method.assert_called_once_with({"testkey": "between"})
|
||||||
|
|
||||||
mock.reset_mock()
|
mock.reset_mock()
|
||||||
pm.unwire(sub)
|
pm.unwire(sub)
|
||||||
|
@ -49,7 +49,7 @@ class PropertyStackTest(TestCase):
|
|||||||
mock = Mock()
|
mock = Mock()
|
||||||
stack.wire(mock.method)
|
stack.wire(mock.method)
|
||||||
layer["testkey"] = "testvalue"
|
layer["testkey"] = "testvalue"
|
||||||
mock.method.assert_called_once_with("testkey", "testvalue")
|
mock.method.assert_called_once_with({"testkey": "testvalue"})
|
||||||
|
|
||||||
def testPropertyChangeEventPriority(self):
|
def testPropertyChangeEventPriority(self):
|
||||||
low_layer = PropertyLayer()
|
low_layer = PropertyLayer()
|
||||||
@ -64,7 +64,7 @@ class PropertyStackTest(TestCase):
|
|||||||
low_layer["testkey"] = "modified low value"
|
low_layer["testkey"] = "modified low value"
|
||||||
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):
|
def testPropertyEventOnLayerAdd(self):
|
||||||
low_layer = PropertyLayer()
|
low_layer = PropertyLayer()
|
||||||
@ -162,7 +162,7 @@ class PropertyStackTest(TestCase):
|
|||||||
mock = Mock()
|
mock = Mock()
|
||||||
stack.wire(mock.method)
|
stack.wire(mock.method)
|
||||||
stack.removeLayer(layer)
|
stack.removeLayer(layer)
|
||||||
mock.method.assert_called_once_with("testkey", None)
|
mock.method.assert_called_once_with({"testkey": None})
|
||||||
mock.reset_mock()
|
mock.reset_mock()
|
||||||
|
|
||||||
layer["testkey"] = "after"
|
layer["testkey"] = "after"
|
||||||
|
Loading…
Reference in New Issue
Block a user