diff --git a/g13gui/g13gui/observer/observer.py b/g13gui/g13gui/observer/observer.py index 580784e..c8ca1f2 100644 --- a/g13gui/g13gui/observer/observer.py +++ b/g13gui/g13gui/observer/observer.py @@ -4,80 +4,7 @@ import unittest from enum import Enum - -class ChangeType(Enum): - ADD = 0 - REMOVE = 1 - MODIFY = 2 - - -class Subject(object): - """Simple class to handle the subject-side of the Observer pattern.""" - - 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: subscribedKeys} - else: - self._observers[observer] = subscribedKeys - - def removeObserver(self, observer): - """Removes an observer from this object""" - if '_observers' in self.__dict__: - if observer in self._observers: - del self._observers[observer] - - def addChange(self, type, key, data=None): - """Schedules a change notification for transmitting later. - - type[ChangeType]: the type of change that occurred. - key[string]: a required name for what field changed. - data[object]: an optional context-dependent object, dict, or - None, specifying what changed. In the case of an ADD or MODIFY, - whatChanged should be the new data. In the case of a DELETE, it should - be the old data (or None). - """ - if '_changes' not in self.__dict__: - self._changes = [(type, key, data)] - else: - self._changes.append((type, key, data)) - - def clearChanges(self): - """Removes all scheduled changes from the change buffer.""" - self._changes = [] - - def notifyChange(self): - raise NotImplementedError('Use Subject.notifyChanged instead') - - def notifyChanged(self): - """Notifies all observers of scheduled changes in the change buffer. - - This method actually does the work of iterating through all observers - and all changes and delivering them to the Observer's onSubjectChanged - method. - - It is safe to call this if there are no changes to send in the buffer, - or there are no observers to send changes to. Note that calling this - when no observers are registered will still flush the change buffer. - """ - if '_observers' in self.__dict__ and '_changes' in self.__dict__: - 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 = [] - - def setProperty(self, propertyName, value, notify=True): - propertyName = '_' + propertyName - self.__dict__[propertyName] = value - self.addChange(ChangeType.MODIFY, propertyName, value) - if notify: - self.notifyChanged() +from g13gui.observer.subject import Subject class Observer(object): @@ -114,12 +41,8 @@ class Observer(object): should be the old data (or None). """ if '_changeTriggers' not in self.__dict__: - raise NotImplementedError( - 'onSubjectChanged(%s, %s, %s, %s) fired with no ' - 'listeners registered!' % - (subject, changeType, key, data)) + return - found = False triggers = ( self._changeTriggers.get((None, Subject.AllKeys)), self._changeTriggers.get((changeType, Subject.AllKeys)), @@ -128,14 +51,8 @@ class Observer(object): for trigger in triggers: if trigger: - found = True trigger(subject, changeType, key, data) - if not found: - raise NotImplementedError( - 'onSubjectChanged(%s, %s, %s, %s) fired without a listener!' - % (subject, changeType, key, data)) - class ObserverTestCase(Observer, unittest.TestCase): def __init__(self, methodName): diff --git a/g13gui/g13gui/observer/observer_tests.py b/g13gui/g13gui/observer/observer_tests.py index 535d244..563177d 100644 --- a/g13gui/g13gui/observer/observer_tests.py +++ b/g13gui/g13gui/observer/observer_tests.py @@ -1,17 +1,21 @@ #!/usr/bin/python import unittest -import observer from builtins import property +from g13gui.observer.observer import Observer +from g13gui.observer.observer import ObserverTestCase +from g13gui.observer.subject import Subject +from g13gui.observer.subject import ChangeType -class TestIncorrectObserver(observer.Observer): + +class TestIncorrectObserver(Observer): def __hash__(self): return hash('TestIncorrectObserver') -class TestSubject(observer.Subject): +class TestSubject(Subject): def __init__(self): self._value = None @@ -24,7 +28,7 @@ class TestSubject(observer.Subject): self.setProperty('value', value) -class ObserverTestCase(observer.ObserverTestCase): +class ObserverTestCase(ObserverTestCase): def setUp(self): self.subject = TestSubject() @@ -42,7 +46,7 @@ class ObserverTestCase(observer.ObserverTestCase): def testSubclassNotificationError(self): testObserver = TestIncorrectObserver() - self.subject.addChange(observer.ChangeType.ADD, 'foo') + self.subject.addChange(ChangeType.ADD, 'foo') self.subject.registerObserver(testObserver) try: @@ -55,25 +59,25 @@ class ObserverTestCase(observer.ObserverTestCase): def testSubclassNotification(self): self.subject.registerObserver(self) - self.subject.addChange(observer.ChangeType.ADD, 'foo', 'bar') + self.subject.addChange(ChangeType.ADD, 'foo', 'bar') self.subject.notifyChanged() self.assertChangeCount(1) - self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'foo') + self.assertChangeNotified(self.subject, 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.addChange(ChangeType.ADD, 'a') + self.subject.addChange(ChangeType.ADD, 'b') + self.subject.addChange(ChangeType.ADD, 'c') self.subject.notifyChanged() self.assertChangeCount(2) - self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'a') + self.assertChangeNotified(self.subject, ChangeType.ADD, 'a') self.nextChange() - self.assertChangeNotified(self.subject, observer.ChangeType.ADD, 'b') + self.assertChangeNotified(self.subject, ChangeType.ADD, 'b') self.nextChange()