-"""
-Whatever fits nowhere else, and/or is too small/trivial
-to merit its own module at this point.
-"""
+"""Attributes whose values are recorded as a timestamped history."""
+from datetime import datetime
+from typing import Any
+from plomtask.db import DatabaseConnection
-class HandledException(Exception):
- """To identify Exceptions based on expected (if faulty) user behavior."""
+class VersionedAttribute:
+ """Attributes whose values are recorded as a timestamped history."""
+
+ def __init__(self,
+ parent: Any, table_name: str, default: str | float) -> None:
+ self.parent = parent
+ self.table_name = table_name
+ self.default = default
+ self.history: dict[str, str | float] = {}
+
+ @property
+ def _newest_timestamp(self) -> str:
+ """Return most recent timestamp."""
+ return sorted(self.history.keys())[-1]
+
+ @property
+ def newest(self) -> str | float:
+ """Return most recent value, or self.default if self.history empty."""
+ if 0 == len(self.history):
+ return self.default
+ return self.history[self._newest_timestamp]
+
+ def set(self, value: str | float) -> None:
+ """Add to self.history if and only if not same value as newest one."""
+ if 0 == len(self.history) \
+ or value != self.history[self._newest_timestamp]:
+ self.history[datetime.now().strftime('%Y-%m-%d %H:%M:%S')] = value
+
+ def at(self, queried_time: str) -> str | float:
+ """Retrieve value of timestamp nearest queried_time from the past."""
+ sorted_timestamps = sorted(self.history.keys())
+ if 0 == len(sorted_timestamps):
+ return self.default
+ selected_timestamp = sorted_timestamps[0]
+ for timestamp in sorted_timestamps[1:]:
+ if timestamp > queried_time:
+ break
+ selected_timestamp = timestamp
+ return self.history[selected_timestamp]
+
+ def save(self, db_conn: DatabaseConnection) -> None:
+ """Save as self.history entries, but first wipe old ones."""
+ db_conn.exec(f'DELETE FROM {self.table_name} WHERE parent = ?',
+ (self.parent.id_,))
+ for timestamp, value in self.history.items():
+ db_conn.exec(f'INSERT INTO {self.table_name} VALUES (?, ?, ?)',
+ (self.parent.id_, timestamp, value))