From 8f46071239fc4f709fa7f612a0575f825b39bd32 Mon Sep 17 00:00:00 2001 From: June Tate-Gans Date: Tue, 27 Apr 2021 18:02:24 -0500 Subject: [PATCH] g13gui: Make observers capable of subscribing to keys This reduces some of the notifications during changes by reducing the scope of changes that are monitored by other components in the system. IOW, this allows keys to only care about their particular changes, rather than all key binding changes in a BindingProfile. --- g13gui/g13gui/observer.py | 23 +++++++++++++---------- g13gui/g13gui/observer_tests.py | 17 ++++++++++++++++- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/g13gui/g13gui/observer.py b/g13gui/g13gui/observer.py index 2a59cec..835a1f2 100644 --- a/g13gui/g13gui/observer.py +++ b/g13gui/g13gui/observer.py @@ -12,8 +12,6 @@ class ChangeType(Enum): class Observer(object): - """Simple interface class to handle Observer-style notifications""" - def onSubjectChanged(self, subject, changeType, key, data=None): """Event handler for observer notifications. @@ -36,18 +34,22 @@ class Observer(object): class Subject(object): """Simple class to handle the subject-side of the Observer pattern.""" - def registerObserver(self, observer): + AllKeys = '' + + def registerObserver(self, observer, subscribedKeys=AllKeys): """Registers an Observer class as an observer of this object""" + if subscribedKeys != Subject.AllKeys: + subscribedKeys = frozenset(subscribedKeys) if '_observers' not in self.__dict__: - self._observers = {observer} + self._observers = {observer: subscribedKeys} else: - self._observers.add(observer) + self._observers[observer] = subscribedKeys def removeObserver(self, observer): """Removes an observer from this object""" if '_observers' in self.__dict__: if observer in self._observers: - self._observers.discard(observer) + del self._observers[observer] def addChange(self, type, key, data=None): """Schedules a change notification for transmitting later. @@ -80,16 +82,17 @@ class Subject(object): when no observers are registered will still flush the change buffer. """ if '_observers' in self.__dict__ and '_changes' in self.__dict__: - for observer in self._observers: - for change in self._changes: - observer.onSubjectChanged(self, *change) + for observer, subscribedKeys in self._observers.items(): + for type, key, data in self._changes: + if subscribedKeys == Subject.AllKeys or key in subscribedKeys: + observer.onSubjectChanged(self, type, key, data) + self._changes = [] class ObserverTestCase(Observer, unittest.TestCase): def __init__(self, methodName): unittest.TestCase.__init__(self, methodName) - self.changes = [] self.clearChanges() def onSubjectChanged(self, subject, type, key, data=None): diff --git a/g13gui/g13gui/observer_tests.py b/g13gui/g13gui/observer_tests.py index 91ef329..a4a3af3 100644 --- a/g13gui/g13gui/observer_tests.py +++ b/g13gui/g13gui/observer_tests.py @@ -5,7 +5,8 @@ import observer class TestIncorrectObserver(observer.Observer): - pass + def __hash__(self): + return hash('TestIncorrectObserver') class TestSubject(observer.Subject): @@ -50,6 +51,20 @@ class ObserverTestCase(observer.ObserverTestCase): self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'foo') self.assertChangeDataEquals('bar') + def testSubscribedKeys(self): + self.subject.registerObserver(self, {'a', 'b'}) + + self.subject.addChange(observer.ChangeType.ADD, 'a') + self.subject.addChange(observer.ChangeType.ADD, 'b') + self.subject.addChange(observer.ChangeType.ADD, 'c') + self.subject.notifyChanged() + + self.assertChangeCount(2) + self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'a') + self.nextChange() + self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'b') + self.nextChange() + if __name__ == '__main__': unittest.main()