[docs]classTextmateCache(Protocol):"""Interface for a Textmate cache."""
[docs]defcache_valid(self,filepath:Path)->bool:""" Check if the cache for the given filepath is valid. :param filepath: The path to the file. :return: True if the cache is valid, False otherwise. """...
[docs]defload(self,filepath:Path)->ContentElement:""" Load the content from the specified filepath. :param filepath: The path to the file to load. :return: The loaded content element. """...
[docs]defsave(self,filePath:Path,element:ContentElement)->None:""" Save the given content element to the specified file path. :param filePath: The file path where the content element should be saved. :param element: The content element to be saved. :return: None """...
[docs]classSimpleCache(TextmateCache):"""A simple cache implementation for storing content elements."""def__init__(self)->None:"""Initialize the SimpleCache."""self._element_cache:dict[str,ContentElement]=dict()self._element_timestamp:dict[str,float]=dict()
[docs]defcache_valid(self,filepath:Path)->bool:"""Check if the cache is valid for the given filepath. :param filepath: The filepath to check. :return: True if the cache is valid, False otherwise. """key=_path_to_key(filepath)ifkeynotinself._element_cache:returnFalsetimestamp=filepath.resolve().stat().st_mtimereturntimestamp==self._element_timestamp[key]
[docs]defload(self,filepath:Path)->ContentElement:"""Load the content element from the cache for the given filepath. :param filepath: The filepath to load the content element from. :return: The loaded content element. """key=_path_to_key(filepath)returnself._element_cache[key]
[docs]defsave(self,filepath:Path,element:ContentElement)->None:"""Save the content element to the cache for the given filepath. :param filepath: The filepath to save the content element to. :param element: The content element to save. :return: None """key=_path_to_key(filepath)self._element_cache[key]=elementself._element_timestamp[key]=filepath.resolve().stat().st_mtime
[docs]classShelveCache(TextmateCache):"""A cache implementation using the shelve module."""def__init__(self)->None:"""Initialize the ShelveCache."""importshelvedatabase_path=CACHE_DIR/"textmate.db"self._database=shelve.open(str(database_path))defexit():self._database.sync()self._database.close()atexit.register(exit)
[docs]defcache_valid(self,filepath:Path)->bool:"""Check if the cache is valid for the given filepath. :param filepath: The filepath to check. :return: True if the cache is valid, False otherwise. """key=_path_to_key(filepath)ifkeynotinself._database:returnFalsetimestamp=filepath.resolve().stat().st_mtimetry:valid=timestamp==self._database[key][0]exceptUnpicklingError:valid=Falseelse:valid=Falsereturnvalid
[docs]defload(self,filepath:Path)->ContentElement:"""Load the content element from the cache for the given filepath. :param filepath: The path for the cached content element. :return: The loaded content element. """key=_path_to_key(filepath)returnself._database[key][1]
[docs]defsave(self,filepath:Path,element:ContentElement)->None:"""Save the content element to the cache for the given filepath. :param filepath: The filepath to save the content element to. :param element: The content element to save. """element._dispatch(nested=True)key=_path_to_key(filepath)timestamp=filepath.resolve().stat().st_mtimeself._database[key]=(timestamp,element)
CACHE:TextmateCache=SimpleCache()
[docs]definit_cache(type:str="simple")->TextmateCache:""" Initialize the cache based on the given type. :param type: The type of cache to initialize. Defaults to "simple". :return: The initialized cache object. """globalCACHEiftype=="shelve":CACHE=ShelveCache()eliftype=="simple":CACHE=SimpleCache()else:raiseNotImplementedError(f"Cache type {type} not implemented.")returnCACHE