- @classmethod
- def get_cache(cls: type[BaseModelInstance]) -> dict[Any, BaseModel[Any]]:
- """Get cache dictionary, create it if not yet existing."""
- if not hasattr(cls, 'cache_'):
- d: dict[Any, BaseModel[Any]] = {}
- cls.cache_ = d
- return cls.cache_
+ def __eq__(self, other: object) -> bool:
+ if not isinstance(other, self.__class__):
+ msg = 'cannot compare to object of different class'
+ raise HandledException(msg)
+ to_hash_me = tuple([self.id_] +
+ [getattr(self, name) for name in self.to_save])
+ to_hash_other = tuple([other.id_] +
+ [getattr(other, name) for name in other.to_save])
+ return hash(to_hash_me) == hash(to_hash_other)
+
+ def save_core(self, db_conn: DatabaseConnection) -> None:
+ """Write bare-bones self (sans connected items), ensuring self.id_.
+
+ Write both to DB, and to cache. To DB, write .id_ and attributes
+ listed in cls.to_save.
+
+ Ensure self.id_ by setting it to what the DB command returns as the
+ last saved row's ID (cursor.lastrowid), EXCEPT if self.id_ already
+ exists as a 'str', which implies we do our own ID creation (so far
+ only the case with the Day class, where it's to be a date string.
+ """
+ values = tuple([self.id_] + [getattr(self, key)
+ for key in self.to_save])
+ q_marks = DatabaseConnection.q_marks_from_values(values)
+ table_name = self.table_name
+ cursor = db_conn.exec(f'REPLACE INTO {table_name} VALUES {q_marks}',
+ values)
+ if not isinstance(self.id_, str):
+ self.id_ = cursor.lastrowid # type: ignore[assignment]
+ self.cache()
+
+ def remove(self, db_conn: DatabaseConnection) -> None:
+ """Remove from DB and cache."""
+ if self.id_ is None or self.__class__.get_cached(self.id_) is None:
+ raise HandledException('cannot remove unsaved item')
+ self.uncache()
+ db_conn.delete_where(self.table_name, 'id', self.id_)