"""Persistent cache."""
from __future__ import annotations
import contextlib
import os
import shutil
import typing as t
import appdirs
import diskcache
from project_config.compat import cached_function, importlib_metadata
[docs]@cached_function
def _directory() -> str:
project_config_metadata = importlib_metadata.metadata("project_config")
return appdirs.user_data_dir( # type: ignore
appname=project_config_metadata["name"],
appauthor=project_config_metadata["author"],
)
[docs]class Cache:
"""Wrapper for a unique :py:class:`diskcache.Cache` instance."""
_cache = diskcache.Cache(_directory())
_expiration_time = 30
def __init__(self) -> None: # pragma: no cover
raise NotImplementedError("Cache is a not instanceable interface.")
[docs] @classmethod
def set(cls, *args: t.Any, **kwargs: t.Any) -> t.Any: # noqa: A003, D102
return cls._cache.set(
*args,
**dict(
expire=cls._expiration_time,
**kwargs,
),
)
[docs] @classmethod
def get(cls, *args: t.Any, **kwargs: t.Any) -> t.Any: # noqa: D102
if os.environ.get("PROJECT_CONFIG_USE_CACHE") == "false":
return None
return cls._cache.get(*args, **kwargs) # pragma: no cover
[docs] @staticmethod
def clean() -> bool:
"""Remove the cache directory."""
with contextlib.suppress(FileNotFoundError):
shutil.rmtree(_directory())
return True
[docs] @staticmethod
def get_directory() -> str:
"""Return the cache directory."""
return _directory()
[docs] @classmethod
def set_expiration_time(
cls,
expiration_time: t.Optional[float] = None,
) -> None:
"""Set the expiration time for the cache.
Args:
expiration_time (float): Time in seconds.
"""
cls._expiration_time = expiration_time # type: ignore