Ditch named tuples for dataclasses.
authorScott Gasch <[email protected]>
Wed, 9 Feb 2022 18:30:44 +0000 (10:30 -0800)
committerScott Gasch <[email protected]>
Wed, 9 Feb 2022 18:30:44 +0000 (10:30 -0800)
camera_utils.py
google_assistant.py
histogram.py
logical_search.py
tests/run_some_dependencies_test.py
text_utils.py

index c789ed61e19d304391c9d10393bcb22094b0b7d7..99ccdb32a5e949e7edd1b6ce89e866b6b6c63119 100644 (file)
@@ -6,7 +6,8 @@ import logging
 import platform
 import subprocess
 import warnings
-from typing import NamedTuple, Optional
+from dataclasses import dataclass
+from typing import Optional
 
 import cv2  # type: ignore
 import numpy as np
@@ -18,19 +19,21 @@ import exceptions
 logger = logging.getLogger(__name__)
 
 
-class RawJpgHsv(NamedTuple):
+@dataclass
+class RawJpgHsv:
     """Raw image bytes, the jpeg image and the HSV (hue saturation value) image."""
 
-    raw: Optional[bytes]
-    jpg: Optional[np.ndarray]
-    hsv: Optional[np.ndarray]
+    raw: Optional[bytes] = None
+    jpg: Optional[np.ndarray] = None
+    hsv: Optional[np.ndarray] = None
 
 
-class SanityCheckImageMetadata(NamedTuple):
+@dataclass
+class SanityCheckImageMetadata:
     """Is a Blue Iris image bad (big grey borders around it) or infrared?"""
 
-    is_bad_image: bool
-    is_infrared_image: bool
+    is_bad_image: bool = False
+    is_infrared_image: bool = False
 
 
 def sanity_check_image(hsv: np.ndarray) -> SanityCheckImageMetadata:
@@ -76,20 +79,26 @@ def fetch_camera_image_from_video_server(
             tmp = np.frombuffer(raw, dtype="uint8")
             logger.debug(
                 'Translated raw content into %s %s with element type %s',
-                tmp.shape, type(tmp), type(tmp[0]),
+                tmp.shape,
+                type(tmp),
+                type(tmp[0]),
             )
             jpg = cv2.imdecode(tmp, cv2.IMREAD_COLOR)
             logger.debug(
                 'Decoded into %s jpeg %s with element type %s',
-                jpg.shape, type(jpg), type(jpg[0][0])
+                jpg.shape,
+                type(jpg),
+                type(jpg[0][0]),
             )
             hsv = cv2.cvtColor(jpg, cv2.COLOR_BGR2HSV)
             logger.debug(
                 'Converted JPG into %s HSV HSV %s with element type %s',
-                hsv.shape, type(hsv), type(hsv[0][0])
+                hsv.shape,
+                type(hsv),
+                type(hsv[0][0]),
             )
-            (_, is_bad_image) = sanity_check_image(hsv)
-            if not is_bad_image:
+            ret = sanity_check_image(hsv)
+            if not ret.is_bad_image:
                 return raw
     except Exception as e:
         logger.exception(e)
index 4a3a58f5947ab335e26ac2fa1c7ce22afd841a93..adfdca49afb99bc3862611649ad5661ab558249c 100644 (file)
@@ -5,7 +5,8 @@ the Google Assistant via a local gateway."""
 
 import logging
 import warnings
-from typing import NamedTuple, Optional
+from dataclasses import dataclass
+from typing import Optional
 
 import requests
 import speech_recognition as sr  # type: ignore
@@ -34,13 +35,14 @@ parser.add_argument(
 )
 
 
-class GoogleResponse(NamedTuple):
+@dataclass
+class GoogleResponse:
     """A response wrapper."""
 
-    success: bool
-    response: str
-    audio_url: str
-    audio_transcription: Optional[str]  # None if not available.
+    success: bool = False
+    response: str = ''
+    audio_url: str = ''
+    audio_transcription: Optional[str] = None  # None if not available.
 
     def __repr__(self):
         return f"""
index 6f9c0f1e41750f0562293ffedfc4d8383a3f0aa8..2657c0bbd6c9f679808b80843b7c4c36c2f2eb1c 100644 (file)
@@ -5,7 +5,7 @@
 
 import math
 from dataclasses import dataclass
-from typing import Dict, Generic, Iterable, List, NamedTuple, Optional, Tuple, TypeVar
+from typing import Dict, Generic, Iterable, List, Optional, Tuple, TypeVar
 
 T = TypeVar("T", int, float)
 Bound = int
index b55e68901501ad2e68a7f45df034866072c3f61b..41ed729fc15df80a4477d3094e4dc980869741aa 100644 (file)
@@ -9,7 +9,8 @@ from __future__ import annotations
 import enum
 import sys
 from collections import defaultdict
-from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, Union
+from dataclasses import dataclass, field
+from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Union
 
 
 class ParseError(Exception):
@@ -20,13 +21,22 @@ class ParseError(Exception):
         self.message = message
 
 
-class Document(NamedTuple):
-    """A tuple representing a searchable document."""
+@dataclass
+class Document:
+    """A class representing a searchable document."""
 
-    docid: str  # a unique idenfier for the document
-    tags: Set[str]  # an optional set of tags
-    properties: List[Tuple[str, str]]  # an optional set of key->value properties
-    reference: Any  # an optional reference to something else
+    # A unique identifier for each document.
+    docid: str = ''
+
+    # A set of tag strings for this document.  May be empty.
+    tags: Set[str] = field(default_factory=set)
+
+    # A list of key->value strings for this document.  May be empty.
+    properties: List[Tuple[str, str]] = field(default_factory=list)
+
+    # An optional reference to something else; interpreted only by
+    # caller code, ignored here.
+    reference: Optional[Any] = None
 
 
 class Operation(enum.Enum):
index ebe61c0029b8b4779317ce2874311b97ea969395..1182f23d33b7eed38705860be639e3508df4f435 100755 (executable)
@@ -27,6 +27,7 @@ class RunSomeDependenciesTest(unittest.TestCase):
             "/home/scott/bin/unscramble.py ethyropadratoyzrhoiectmi --trace_memory >& /dev/null",
             "/home/scott/bin/cron.py --command='sleep 0' --lockfile=/tmp/deleteme_lock >& /dev/null",
             "/home/scott/cron/manage_switch_off_timers.py >& /dev/null",
+            "/home/scott/bin/smart_device.py cabin and outside and timeout:* -c print >& /dev/null",
         ]
         for command in commands:
             try:
index 7910990f2a58ec318ba6a68a7ba9e87ff415c77b..720bf20561a63bcd5c1afeba42658c8924566adc 100644 (file)
@@ -8,18 +8,20 @@ import logging
 import math
 import sys
 from collections import defaultdict
-from typing import Dict, Generator, List, Literal, NamedTuple, Optional, Tuple
+from dataclasses import dataclass
+from typing import Dict, Generator, List, Literal, Optional, Tuple
 
 from ansi import fg, reset
 
 logger = logging.getLogger(__file__)
 
 
-class RowsColumns(NamedTuple):
+@dataclass
+class RowsColumns:
     """Row + Column"""
 
-    rows: int
-    columns: int
+    rows: int = 0
+    columns: int = 0
 
 
 def get_console_rows_columns() -> RowsColumns: