Easier and more self documenting patterns for loading/saving Persistent
[python_utils.git] / waitable_presence.py
index e1da4310b76a77693aa505452e0f3748c4fcc62d..9d79c6c5d61e1065f1444670c3ce24c1b9b7cd0f 100644 (file)
@@ -1,9 +1,10 @@
 #!/usr/bin/env python3
 
+# © Copyright 2021-2022, Scott Gasch
+
 """A PresenceDetector that is waitable.  This is not part of
 base_presence.py because I do not want to bring these dependencies
 into that lower-level module (especially state_tracker).
-
 """
 
 import datetime
@@ -24,7 +25,7 @@ class WaitablePresenceDetectorWithMemory(state_tracker.WaitableAutomaticStateTra
     """
     This is a waitable class that keeps a PresenceDetector internally
     and periodically polls it to detect changes in presence in a
-    particular location.  Example suggested usage pattern:
+    particular location.  Example suggested usage pattern::
 
         detector = waitable_presence.WaitablePresenceDetectorWithMemory(60.0)
         while True:
@@ -41,13 +42,17 @@ class WaitablePresenceDetectorWithMemory(state_tracker.WaitableAutomaticStateTra
         self,
         override_update_interval_sec: float = 60.0,
         override_location: Location = site_config.get_location(),
+        injected_presence_detector: Optional[base_presence.PresenceDetection] = None,
     ) -> None:
         self.last_someone_is_home: Optional[bool] = None
         self.someone_is_home: Optional[bool] = None
         self.everyone_gone_since: Optional[datetime.datetime] = None
         self.someone_home_since: Optional[datetime.datetime] = None
         self.location = override_location
-        self.detector: base_presence.PresenceDetection = base_presence.PresenceDetection()
+        if injected_presence_detector is not None:
+            self.detector: base_presence.PresenceDetection = injected_presence_detector
+        else:
+            self.detector = base_presence.PresenceDetection()
         super().__init__(
             {
                 'poll_presence': override_update_interval_sec,
@@ -70,7 +75,7 @@ class WaitablePresenceDetectorWithMemory(state_tracker.WaitableAutomaticStateTra
             raise Exception(f'Unknown update type {update_id} in {__file__}')
 
     def poll_presence(self, now: datetime.datetime) -> None:
-        logger.debug(f'Checking presence in {self.location} now...')
+        logger.debug('Checking presence in %s now...', self.location)
         self.detector.update()
         if self.detector.is_anyone_in_location_now(self.location):
             self.someone_is_home = True
@@ -87,14 +92,14 @@ class WaitablePresenceDetectorWithMemory(state_tracker.WaitableAutomaticStateTra
             logger.debug('PresenceDetector is incomplete; trying to reinitialize...')
             self.detector = base_presence.PresenceDetection()
 
-    def is_someone_home(self) -> Tuple[bool, datetime.datetime]:
+    def is_someone_home(self) -> Optional[Tuple[bool, datetime.datetime]]:
         """Returns a tuple of a bool that indicates whether someone is home
         and a datetime that indicates how long either someone has been
         home or no one has been home.
 
         """
         if self.someone_is_home is None:
-            raise Exception("Too Soon!")
+            return None  # checked too soon, wait a bit.
         if self.someone_is_home:
             assert self.someone_home_since is not None
             return (True, self.someone_home_since)