Add some docs and doctests to things that have 0% coverage.
authorScott Gasch <[email protected]>
Sat, 30 Apr 2022 17:59:48 +0000 (10:59 -0700)
committerScott Gasch <[email protected]>
Sat, 30 Apr 2022 17:59:48 +0000 (10:59 -0700)
persistent.py
smart_home/cameras.py
smart_home/chromecasts.py
smart_home/registry.py
smart_home/thermometers.py

index 27aa4b32aed2fdb299e2c1031a041a19b3c385a5..b42a5c0e3036a35d76dc0c8f32374d029e94fd53 100644 (file)
@@ -64,7 +64,23 @@ class Persistent(ABC):
 
 
 def was_file_written_today(filename: str) -> bool:
-    """Returns True if filename was written today."""
+    """Returns True if filename was written today.
+
+    >>> import os
+    >>> filename = f'/tmp/testing_persistent_py_{os.getpid()}'
+    >>> os.system(f'touch {filename}')
+    0
+    >>> was_file_written_today(filename)
+    True
+    >>> os.system(f'touch -d 1974-04-15T01:02:03.99 {filename}')
+    0
+    >>> was_file_written_today(filename)
+    False
+    >>> os.system(f'/bin/rm -f {filename}')
+    0
+    >>> was_file_written_today(filename)
+    False
+    """
 
     if not file_utils.does_file_exist(filename):
         return False
@@ -82,7 +98,22 @@ def was_file_written_within_n_seconds(
     """Returns True if filename was written within the pas limit_seconds
     seconds.
 
+    >>> import os
+    >>> filename = f'/tmp/testing_persistent_py_{os.getpid()}'
+    >>> os.system(f'touch {filename}')
+    0
+    >>> was_file_written_within_n_seconds(filename, 60)
+    True
+    >>> import time
+    >>> time.sleep(2.0)
+    >>> was_file_written_within_n_seconds(filename, 2)
+    False
+    >>> os.system(f'/bin/rm -f {filename}')
+    0
+    >>> was_file_written_within_n_seconds(filename, 60)
+    False
     """
+
     if not file_utils.does_file_exist(filename):
         return False
 
@@ -169,3 +200,9 @@ class persistent_autoloaded_singleton(object):
             return self.instance
 
         return _load
+
+
+if __name__ == '__main__':
+    import doctest
+
+    doctest.testmod()
index 8643611811f69f61a6c46f37f9c6680c0479d441..e8f164b3c0a6f1529347c79400b1036623a87d58 100644 (file)
@@ -5,6 +5,7 @@
 """Utilities for dealing with the webcams."""
 
 import logging
+from typing import Optional
 
 import scott_secrets
 import smart_home.device as dev
@@ -29,9 +30,12 @@ class BaseCamera(dev.Device):
         super().__init__(name.strip(), mac.strip(), keywords)
         self.camera_name = BaseCamera.camera_mapping.get(name, None)
 
-    def get_stream_url(self) -> str:
+    def get_stream_url(self) -> Optional[str]:
+        """Get the URL for the webcam's live stream.  Return None on error."""
+
         name = self.camera_name
-        assert name is not None
+        if not name:
+            return None
         if name == 'driveway':
             return f'http://10.0.0.226:8080/{scott_secrets.SHINOBI_KEY1}/mjpeg/{scott_secrets.SHINOBI_KEY2}/driveway'
         else:
index 408ccf0e12ff3b1702ef7cd4b63d42c357fac7db..3bd45f126e07e6f60d0251bd7249703f21f0aad7 100644 (file)
@@ -2,7 +2,7 @@
 
 # © Copyright 2021-2022, Scott Gasch
 
-"""Utilities for dealing with the webcams."""
+"""Utilities for dealing with the chromecasts."""
 
 import atexit
 import datetime
index d63474da56f98bc44d78a221f47c3f4fd7d04971..8ca7f3b96dad4cc25807b59d948803e95e8c72ca 100644 (file)
@@ -83,9 +83,9 @@ class SmartHomeRegistry(object):
                 self._keywords_by_name[name] = keywords
                 self._keywords_by_mac[mac] = keywords
                 self._names_by_mac[mac] = name
-                self.index_device(name, keywords, mac)
+                self._index_device(name, keywords, mac)
 
-    def index_device(self, name: str, keywords: str, mac: str) -> None:
+    def _index_device(self, name: str, keywords: str, mac: str) -> None:
         properties = [("name", name)]
         tags = set()
         for kw in keywords.split():
@@ -111,9 +111,30 @@ class SmartHomeRegistry(object):
         return s
 
     def get_keywords_by_name(self, name: str) -> Optional[str]:
+        """Given the name of a device, get its keywords.
+
+        >>> reg = SmartHomeRegistry('/home/scott/bin/network_mac_addresses.txt')
+        >>> reg.get_keywords_by_name('near_kitchen_lamp')
+        'wifi smart light goog meross test'
+
+        >>> reg.get_keywords_by_name('unknown') is None
+        True
+
+        """
         return self._keywords_by_name.get(name, None)
 
     def get_macs_by_name(self, name: str) -> Set[str]:
+        """Given the name of a device, get its MAC address(es)
+
+        >>> reg = SmartHomeRegistry('/home/scott/bin/network_mac_addresses.txt')
+        >>> reg.get_macs_by_name('near_kitchen_lamp')
+        {'34:29:8F:12:34:8E'}
+
+        >>> reg.get_macs_by_name('unknown')
+        set()
+
+        """
+
         retval = set()
         for (mac, lname) in self._names_by_mac.items():
             if name in lname:
@@ -121,6 +142,19 @@ class SmartHomeRegistry(object):
         return retval
 
     def get_macs_by_keyword(self, keyword: str) -> Set[str]:
+        """Given a keyword, return the set of MAC address(es) that have
+        that keyword.
+
+        >>> reg = SmartHomeRegistry('/home/scott/bin/network_mac_addresses.txt')
+        >>> r = reg.get_macs_by_keyword('test')
+        >>> e = set(['34:29:8F:12:26:74' , '34:29:8F:12:34:8E'])
+        >>> r == e
+        True
+
+        >>> reg.get_macs_by_keyword('unknown')
+        set()
+
+        """
         retval = set()
         for (mac, keywords) in self._keywords_by_mac.items():
             if keyword in keywords:
@@ -128,11 +162,15 @@ class SmartHomeRegistry(object):
         return retval
 
     def get_device_by_name(self, name: str) -> Optional[device.Device]:
+        """Given a name, return its Device object."""
+
         if name in self._macs_by_name:
             return self.get_device_by_mac(self._macs_by_name[name])
         return None
 
     def get_all_devices(self) -> List[device.Device]:
+        """Return a list of all known devices."""
+
         retval = []
         for mac, _ in self._keywords_by_mac.items():
             if mac is not None:
@@ -142,6 +180,8 @@ class SmartHomeRegistry(object):
         return retval
 
     def get_device_by_mac(self, mac: str) -> Optional[device.Device]:
+        """Given a MAC address, return its Device object."""
+
         if mac in self._keywords_by_mac:
             name = self._names_by_mac[mac]
             kws = self._keywords_by_mac[mac]
@@ -197,7 +237,7 @@ class SmartHomeRegistry(object):
         return None
 
     def query(self, query: str) -> List[device.Device]:
-        """Evaluates a lighting query expression formed of keywords to search
+        """Evaluates a device query expression formed of keywords to search
         for, logical operators (and, or, not), and parenthesis.
         Returns a list of matching lights.
         """
@@ -211,3 +251,9 @@ class SmartHomeRegistry(object):
                     if dev is not None:
                         retval.append(dev)
         return retval
+
+
+if __name__ == '__main__':
+    import doctest
+
+    doctest.testmod()
index 73117bc1a3cccddf0c22be8ab8cb10572b3b41f8..4531c618fc17b749f172abaa301863646f67a0a0 100644 (file)
@@ -28,6 +28,22 @@ class ThermometerRegistry(object):
         }
 
     def read_temperature(self, location: str, *, convert_to_fahrenheit=False) -> Optional[float]:
+        """Read the current value of a thermometer (in celsius unless
+        convert_to_fahrenheit is True) and return it.  Return None on
+        error.
+
+        >>> registry = ThermometerRegistry()
+        >>> registry.read_temperature('unknown') is None
+        True
+
+        >>> temp = registry.read_temperature('house_computer_closet')
+        >>> temp is None
+        False
+        >>> temp > 0.0
+        True
+
+        """
+
         record = self.thermometers.get(location, None)
         if record is None:
             logger.error(
@@ -36,6 +52,7 @@ class ThermometerRegistry(object):
                 self.thermometers.keys(),
             )
             return None
+
         url = f'http://{record[0]}/~pi/{record[1]}'
         logger.debug('Constructed URL: %s', url)
         try:
@@ -54,3 +71,9 @@ class ThermometerRegistry(object):
             if www is not None:
                 www.close()
         return temp
+
+
+if __name__ == '__main__':
+    import doctest
+
+    doctest.testmod()