mpd-now-playable/src/mpd_now_playable/cache.py

58 lines
1.4 KiB
Python
Raw Normal View History

from __future__ import annotations
from contextlib import suppress
from typing import Any, Generic, Optional, TypeVar
from aiocache import Cache
from aiocache.serializers import BaseSerializer
from pydantic.type_adapter import TypeAdapter
from yarl import URL
T = TypeVar("T")
with suppress(ImportError):
import ormsgpack
class OrmsgpackSerializer(BaseSerializer, Generic[T]):
DEFAULT_ENCODING = None
def __init__(self, schema: TypeAdapter[T]):
super().__init__()
self.schema = schema
def dumps(self, value: T) -> bytes:
return ormsgpack.packb(self.schema.dump_python(value))
def loads(self, value: Optional[bytes]) -> T | None:
if value is None:
return None
data = ormsgpack.unpackb(value)
return self.schema.validate_python(data)
def make_cache(schema: TypeAdapter[T], url: URL, namespace: str = "") -> Cache[T]:
backend = Cache.get_scheme_class(url.scheme)
if backend == Cache.MEMORY:
return Cache(backend)
kwargs: dict[str, Any] = dict(url.query)
if url.path:
kwargs.update(backend.parse_uri_path(url.path))
if url.host:
kwargs["endpoint"] = url.host
if url.port:
kwargs["port"] = url.port
if url.password:
kwargs["password"] = url.password
namespace = ":".join(s for s in [kwargs.pop("namespace", ""), namespace] if s)
serializer = OrmsgpackSerializer(schema)
return Cache(backend, serializer=serializer, namespace=namespace, **kwargs)