from Daisy.Daisy import Daisy import os import logging import msgpack # TODO: Dumping to cacheFile logger = logging.getLogger("__main__." + __name__) class Cache: """ In memory collection of Daisy records, provides a search functionality currently utilized by `Daisy.Catch.Catch` `🔗 Source `__ """ def __init__( self, daisyCryptography, filepaths=None, cacheFile=None, path: str = "daisy", walk: bool = False ): """ Parameters ---------- daisyCryptography: Daisy.CryptographyUtil.SteelPetal Record cryptography reference filepaths Either a list of filepaths to load or None cacheFile Path to a cache file which is a collection of paths to load or None path: str Path prefix to load records from walk: bool Whether to automatically walk the path and load records """ self.daisyCryptography = daisyCryptography self.data = {} self.path = path if not os.path.exists(self.path): os.makedirs(self.path) if filepaths is not None: for fp in filepaths: fp = path + "/" + fp if os.path.isfile(fp): self.data[fp] = Daisy(fp, daisyCryptography) elif cacheFile is not None: self.cacheFile = cacheFile with open(cacheFile, "r") as f: for fp in f.read().split("\n"): self.data[fp] = Daisy(fp, daisyCryptography) elif walk: for root, dirs, files in os.walk(self.path): for p in dirs + files: if not (".json" in p): if not (".md" in p): tpath = root + "/" + p self.data[tpath] = Daisy(tpath, daisyCryptography) def create(self, path: str, data: dict, remote=False): """ Create new record Parameters ---------- path: str Path to create record at data: dict Data to populate record with remote: bool Whether this is a reference to a distributed file (not implemented yet) """ if not remote: with open(self.path + "/" + path, "wb") as f: f.write(msgpack.dumps(data)) logger.debug("Done creating record") self.data[path] = Daisy(self.path + "/" + path, self.daisyCryptography) logger.debug("Done loading to Daisy") return self.data[path] else: logger.debug("Not that (you shouldn't be here yet, remote Daisy links aren't ready yet)") # TODO: Full remote path functionality pass # self.data[path] = Ref(path, remote) # return self.data[path] def get(self, path: str): """ Get record at path, else return False path: str Path of record """ if path in self.data.keys(): return self.data[path] else: if os.path.exists(self.path + "/" + path): self.data[path] = Daisy(self.path + "/" + path, self.daisyCryptography) return self.data[path] else: path = self.path + "/" + path logger.debug(f"File {path} does not exist") return False def refresh(self): """ Reload from disk to memory """ for key in self.data.keys(): self.data[key].read() def search(self, keydict: dict, strict: bool = True): """ Search cache for record for records with keys and values matching those in the keydict keydict: dict strict: bool Whether to require all keys/values match """ results = [] for key, val in self.data.items(): val = val.get() if strict and type(val) is not str: addcheck = False for k, v in keydict.items(): if k in val.keys(): if v in val[k]: addcheck = True else: addcheck = False break if addcheck: results.append([key, val]) elif type(val) is not str: for k, v in keydict.items(): if k in val.keys(): if v in val[k]: results.append([key, val]) return results