From a9cbb51774d8f3d8bc7515fc04914c38b2fdc82b Mon Sep 17 00:00:00 2001
From: Antonio Caceres <antonio@antonio-caceres.com>
Date: Mon, 14 Oct 2024 17:01:04 -0700
Subject: [PATCH] Add abstract classes and Final to type hinting.

---
 src/abstract.py     | 27 +++++++++++++++++++++++++++
 src/interact.py     |  3 ++-
 src/morse_code.py   |  4 ++--
 src/morse_engine.py | 19 +++++++++++--------
 src/prox_pulse.py   |  5 +++--
 src/pulse.py        | 13 ++++++++-----
 src/symbols.py      |  4 +++-
 7 files changed, 56 insertions(+), 19 deletions(-)
 create mode 100644 src/abstract.py

diff --git a/src/abstract.py b/src/abstract.py
new file mode 100644
index 0000000..37953cf
--- /dev/null
+++ b/src/abstract.py
@@ -0,0 +1,27 @@
+from abc import ABC, abstractmethod
+
+
+class ProximitySensor(ABC):
+    """Abstract proximity sensor."""
+
+    @property
+    @abstractmethod
+    def proximity(self) -> int:
+        ...
+
+
+class LEDController(ABC):
+    """Abstract LED controller."""
+
+    @abstractmethod
+    def fill(self, color: tuple[int, int, int]) -> None:
+        ...
+
+
+class TouchSensor(ABC):
+    """Abstract touch sensor."""
+
+    @property
+    @abstractmethod
+    def value(self) -> bool:
+        ...
diff --git a/src/interact.py b/src/interact.py
index ced534e..90b1a5b 100644
--- a/src/interact.py
+++ b/src/interact.py
@@ -1,9 +1,10 @@
+from .abstract import LEDController, ProximitySensor, TouchSensor
 from .pulse import run_simple_pulse
 from .prox_pulse import run_prox_pulse
 from .morse_engine import run_morse_engine
 
 
-def run(apds, pixels, touch):
+def run(apds: ProximitySensor, pixels: LEDController, touch: TouchSensor):
     """
     Runs the selected demo on the Trinkey.
 
diff --git a/src/morse_code.py b/src/morse_code.py
index 8613a3f..5e597d8 100644
--- a/src/morse_code.py
+++ b/src/morse_code.py
@@ -1,7 +1,7 @@
 from .symbols import MORSE_SYMBOL_TO_LETTER, InvalidSymbolError
 
 
-def append_morse_symbol(message, symbol):
+def append_morse_symbol(message: str, symbol: str) -> str:
     """
     Decodes a Morse code symbol and appends the corresponding character to the 
     message.
@@ -21,7 +21,7 @@ def append_morse_symbol(message, symbol):
     raise InvalidSymbolError()
 
 
-def translate_message(morse):
+def translate_message(morse: str) -> str:
     """
     Translates a Morse code message into an English string.
 
diff --git a/src/morse_engine.py b/src/morse_engine.py
index a561aaf..c47d477 100644
--- a/src/morse_engine.py
+++ b/src/morse_engine.py
@@ -1,13 +1,16 @@
 import time
+from typing import Final
+
 from src import morse_code
+from .abstract import LEDController, TouchSensor, ProximitySensor
 
 # Constants (Keep same or tests will break)
-THRESHOLD = 75
-UNIT_TIME = 0.24
+THRESHOLD: Final[int] = 75
+UNIT_TIME: Final[float] = 0.24
 
-RED = (255, 0, 0)
-YELLOW = (220, 160, 0)
-GREEN = (0, 255, 0)
+RED   : Final[tuple[int, int, int]] = (255, 0,   0)
+YELLOW: Final[tuple[int, int, int]] = (220, 160, 0)
+GREEN : Final[tuple[int, int, int]] = (0,   255, 0)
 
 # Legacy ham radio license requirement
 # - 0.24 sec unit time (5 words per minute)
@@ -15,7 +18,7 @@ GREEN = (0, 255, 0)
 # - 0.034 sec unit time (35 words per minute)
 
 
-def set_color(elapsed_t, px):
+def set_color(elapsed_t: float, px: LEDController):
     """
     Lights the LEDs on the trinkey depending on the length of input.
     
@@ -26,7 +29,7 @@ def set_color(elapsed_t, px):
     pass
 
 
-def add_mark(elapsed_t):
+def add_mark(elapsed_t: float) -> str:
     """
     Determines if input is a dot (.), dash (-), or nothing ("") based 
     on the length of input.
@@ -40,7 +43,7 @@ def add_mark(elapsed_t):
     pass
 
 
-def run_morse_engine(apds, pixels, touch):
+def run_morse_engine(apds: ProximitySensor, pixels: LEDController, touch: TouchSensor):
     """
     Runs Morse code translation based on proximity input.
 
diff --git a/src/prox_pulse.py b/src/prox_pulse.py
index 1fdaf6e..4ec40c1 100644
--- a/src/prox_pulse.py
+++ b/src/prox_pulse.py
@@ -1,5 +1,6 @@
 import time
 from .pulse import pulse
+from .abstract import LEDController, ProximitySensor
 
 THRESHOLD = 75
 
@@ -7,7 +8,7 @@ RED = (150, 10, 10)
 GREEN = (30, 100, 10)
 
 
-def prox_pulse(px, color, prox):
+def prox_pulse(px: LEDController, color: tuple[int, int, int], prox: int) -> None:
     """
     Maps proximity value to pulse duration and calls pulse.
 
@@ -19,7 +20,7 @@ def prox_pulse(px, color, prox):
     pass  # Delete this line when you start coding!
 
 
-def run_prox_pulse(apds, pixels):
+def run_prox_pulse(apds: ProximitySensor, pixels: LEDController) -> None:
     """
     Runs proximity-based pulsing demo.
 
diff --git a/src/pulse.py b/src/pulse.py
index aadc95e..ebfbe61 100644
--- a/src/pulse.py
+++ b/src/pulse.py
@@ -1,11 +1,14 @@
 import time
+from typing import Final
 
-THRESHOLD = 75
-BLUE = (0, 0, 255)
-TIME = 1
+from .abstract import LEDController
 
+THRESHOLD: Final[int] = 75
+BLUE: Final[tuple[int, int, int]] = (0, 0, 255)
+TIME: Final[int] = 1
 
-def pulse(px, color, duration):
+
+def pulse(px: LEDController, color: tuple[int, int, int], duration: float):
     """
     Fills pixels with a color for a duration, then turns them off.
 
@@ -17,7 +20,7 @@ def pulse(px, color, duration):
     pass  # Delete this line when you start coding!
 
 
-def run_simple_pulse(pixels):
+def run_simple_pulse(pixels: LEDController):
     """
     Runs a simple pulse demo.
 
diff --git a/src/symbols.py b/src/symbols.py
index 9282f35..11ab20c 100644
--- a/src/symbols.py
+++ b/src/symbols.py
@@ -1,4 +1,6 @@
-MORSE_SYMBOL_TO_LETTER = {
+from typing import Final
+
+MORSE_SYMBOL_TO_LETTER: Final[dict[str, str]] = {
     ".-": "A",
     "-...": "B",
     "-.-.": "C",
-- 
GitLab