"""Close DB connection."""
self.conn.close()
- def rewrite_relations(self, table_name: str, key: str, target: int,
+ def rewrite_relations(self, table_name: str, key: str, target: int | str,
rows: list[list[Any]]) -> None:
"""Rewrite relations in table_name to target, with rows values."""
self.delete_where(table_name, key, target)
"""Template for most of the models we use/derive from the DB."""
table_name = ''
to_save: list[str] = []
+ to_save_versioned: list[str] = []
+ to_save_relations: list[tuple[str, str, str]] = []
id_: None | BaseModelId
cache_: dict[BaseModelId, Self]
raise HandledException(msg)
self.id_ = id_
+ def __eq__(self, other: object) -> bool:
+ if not isinstance(other, self.__class__):
+ return False
+ 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 __lt__(self, other: Any) -> bool:
+ if not isinstance(other, self.__class__):
+ msg = 'cannot compare to object of different class'
+ raise HandledException(msg)
+ assert isinstance(self.id_, int)
+ assert isinstance(other.id_, int)
+ return self.id_ < other.id_
+
@classmethod
def get_cached(cls: type[BaseModelInstance],
id_: BaseModelId) -> BaseModelInstance | None:
items[item.id_] = item
return list(items.values())
- 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_.
+ def save(self, db_conn: DatabaseConnection) -> None:
+ """Write self to DB and cache and ensure .id_.
Write both to DB, and to cache. To DB, write .id_ and attributes
- listed in cls.to_save.
+ listed in cls.to_save[_versioned|_relations].
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
if not isinstance(self.id_, str):
self.id_ = cursor.lastrowid # type: ignore[assignment]
self.cache()
+ for attr_name in self.to_save_versioned:
+ getattr(self, attr_name).save(db_conn)
+ for table, column, attr_name in self.to_save_relations:
+ assert isinstance(self.id_, (int, str))
+ db_conn.rewrite_relations(table, column, self.id_,
+ [[i.id_] for i
+ in getattr(self, attr_name)])
def remove(self, db_conn: DatabaseConnection) -> None:
- """Remove from DB and cache."""
+ """Remove from DB and cache, including dependencies."""
if self.id_ is None or self.__class__.get_cached(self.id_) is None:
raise HandledException('cannot remove unsaved item')
+ for attr_name in self.to_save_versioned:
+ getattr(self, attr_name).remove(db_conn)
+ for table, column, attr_name in self.to_save_relations:
+ db_conn.delete_where(table, column, self.id_)
self.uncache()
db_conn.delete_where(self.table_name, 'id', self.id_)