X-Git-Url: https://plomlompom.com/repos/%7B%7Bdb.prefix%7D%7D/static/git-favicon.png?a=blobdiff_plain;f=plomtask%2Fdb.py;h=b3f1db00986b1142f5f31be34060864840ab5bdc;hb=21df71ef1fde304b158da5989692c01f463515b5;hp=797b08e8412809e3ac23bb7f04fc24fef955be03;hpb=8f28c8c685fa91b9cbabb4b424da4091e52058cf;p=plomtask diff --git a/plomtask/db.py b/plomtask/db.py index 797b08e..b3f1db0 100644 --- a/plomtask/db.py +++ b/plomtask/db.py @@ -274,24 +274,58 @@ class BaseModel(Generic[BaseModelId]): @property def as_dict(self) -> dict[str, object]: - """Return self as (json.dumps-coompatible) dict.""" - d: dict[str, object] = {'id': self.id_} + """Return self as (json.dumps-compatible) dict.""" + library: dict[str, dict[str | int, object]] = {} + d: dict[str, object] = {'id': self.id_, '_library': library} + for to_save in self.to_save: + attr = getattr(self, to_save) + if hasattr(attr, 'as_dict_into_reference'): + d[to_save] = attr.as_dict_into_reference(library) + else: + d[to_save] = attr if len(self.to_save_versioned) > 0: d['_versioned'] = {} - for k in self.to_save: - attr = getattr(self, k) - if hasattr(attr, 'as_dict'): - d[k] = attr.as_dict - d[k] = attr for k in self.to_save_versioned: attr = getattr(self, k) assert isinstance(d['_versioned'], dict) d['_versioned'][k] = attr.history for r in self.to_save_relations: attr_name = r[2] - d[attr_name] = [x.as_dict for x in getattr(self, attr_name)] + l: list[int | str] = [] + for rel in getattr(self, attr_name): + l += [rel.as_dict_into_reference(library)] + d[attr_name] = l return d + def as_dict_into_reference(self, + library: dict[str, dict[str | int, object]] + ) -> int | str: + """Return self.id_ while writing .as_dict into library.""" + def into_library(library: dict[str, dict[str | int, object]], + cls_name: str, + id_: str | int, + d: dict[str, object] + ) -> None: + if cls_name not in library: + library[cls_name] = {} + if id_ in library[cls_name]: + if library[cls_name][id_] != d: + msg = 'Unexpected inequality of entries for ' +\ + f'_library at: {cls_name}/{id_}' + raise HandledException(msg) + else: + library[cls_name][id_] = d + as_dict = self.as_dict + assert isinstance(as_dict['_library'], dict) + for cls_name, dict_of_objs in as_dict['_library'].items(): + for id_, obj in dict_of_objs.items(): + into_library(library, cls_name, id_, obj) + del as_dict['_library'] + assert self.id_ is not None + into_library(library, self.__class__.__name__, self.id_, as_dict) + assert isinstance(as_dict['id'], (int, str)) + return as_dict['id'] + # cache management # (we primarily use the cache to ensure we work on the same object in # memory no matter where and how we retrieve it, e.g. we don't want @@ -337,9 +371,8 @@ class BaseModel(Generic[BaseModelId]): def _get_cached(cls: type[BaseModelInstance], id_: BaseModelId) -> BaseModelInstance | None: """Get object of id_ from class's cache, or None if not found.""" - # pylint: disable=consider-iterating-dictionary cache = cls.get_cache() - if id_ in cache.keys(): + if id_ in cache: obj = cache[id_] assert isinstance(obj, cls) return obj