From 0a0ecfc9bcc89eda18a981e486e75ff565ade683 Mon Sep 17 00:00:00 2001
From: June Tate-Gans <june@theonelab.com>
Date: Sun, 2 May 2021 23:48:20 -0500
Subject: [PATCH] observer: Finish migrating Subject

---
 g13gui/g13gui/observer/observer.py       | 87 +-----------------------
 g13gui/g13gui/observer/observer_tests.py | 28 ++++----
 2 files changed, 18 insertions(+), 97 deletions(-)

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()