Module genshin.client.cache
Cache for client.
Classes
class BaseCache
-
Base cache for the client.
Expand source code
class BaseCache(abc.ABC): """Base cache for the client.""" @abc.abstractmethod async def get(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get an object with a key.""" @abc.abstractmethod async def set(self, key: typing.Any, value: typing.Any) -> None: """Save an object with a key.""" @abc.abstractmethod async def get_static(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get a static object with a key.""" @abc.abstractmethod async def set_static(self, key: typing.Any, value: typing.Any) -> None: """Save a static object with a key."""
Ancestors
- abc.ABC
Subclasses
Methods
async def get(self, key: typing.Any) ‑> Optional[Any]
-
Get an object with a key.
async def get_static(self, key: typing.Any) ‑> Optional[Any]
-
Get a static object with a key.
async def set(self, key: typing.Any, value: typing.Any) ‑> None
-
Save an object with a key.
async def set_static(self, key: typing.Any, value: typing.Any) ‑> None
-
Save a static object with a key.
class Cache (maxsize: int = 1024, *, ttl: float = 3600, static_ttl: float = 86400)
-
Standard implementation of the cache.
Expand source code
class Cache(BaseCache): """Standard implementation of the cache.""" cache: dict[typing.Any, tuple[float, typing.Any]] maxsize: int ttl: float static_ttl: float def __init__(self, maxsize: int = 1024, *, ttl: float = HOUR, static_ttl: float = DAY) -> None: self.cache = {} self.maxsize = maxsize self.ttl = ttl self.static_ttl = static_ttl def __len__(self) -> int: self._clear_cache() return len(self.cache) def _clear_cache(self) -> None: """Clear timed-out items.""" # since this is always called from an async function we don't need locks now = time.time() for key, value in self.cache.copy().items(): if value[0] < now: del self.cache[key] if len(self.cache) > self.maxsize: overflow = len(self.cache) - self.maxsize keys = list(self.cache.keys())[:overflow] for key in keys: del self.cache[key] async def get(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get an object with a key.""" self._clear_cache() if key not in self.cache: return None return self.cache[key][1] async def set(self, key: typing.Any, value: typing.Any) -> None: """Save an object with a key.""" self.cache[key] = (time.time() + self.ttl, value) self._clear_cache() async def get_static(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get a static object with a key.""" return await self.get(key) async def set_static(self, key: typing.Any, value: typing.Any) -> None: """Save a static object with a key.""" self.cache[key] = (time.time() + self.static_ttl, value) self._clear_cache()
Ancestors
- BaseCache
- abc.ABC
Subclasses
Class variables
var cache : dict[typing.Any, tuple[float, typing.Any]]
var maxsize : int
var static_ttl : float
var ttl : float
Inherited members
class RedisCache (redis: aioredis.Redis, *, ttl: int = 3600, static_ttl: int = 86400)
-
Redis implementation of the cache.
Expand source code
class RedisCache(BaseCache): """Redis implementation of the cache.""" redis: aioredis.Redis ttl: int static_ttl: int def __init__(self, redis: aioredis.Redis, *, ttl: int = HOUR, static_ttl: int = DAY) -> None: self.redis = redis self.ttl = ttl self.static_ttl = static_ttl def serialize_key(self, key: typing.Any) -> str: """Serialize a key by turning it into a string.""" return str(key) def serialize_value(self, value: typing.Any) -> typing.Union[str, bytes]: """Serialize a value by turning it into bytes.""" return json.dumps(value) def deserialize_value(self, value: bytes) -> typing.Any: """Deserialize a value back into data.""" return json.loads(value) async def get(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get an object with a key.""" value = typing.cast("typing.Optional[bytes]", await self.redis.get(self.serialize_key(key))) # pyright: ignore if value is None: return None return self.deserialize_value(value) async def set(self, key: typing.Any, value: typing.Any) -> None: """Save an object with a key.""" await self.redis.set( # pyright: ignore self.serialize_key(key), self.serialize_value(value), ex=self.ttl, ) async def get_static(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get a static object with a key.""" return await self.get(key) async def set_static(self, key: typing.Any, value: typing.Any) -> None: """Save a static object with a key.""" await self.redis.set( # pyright: ignore self.serialize_key(key), self.serialize_value(value), ex=self.static_ttl, )
Ancestors
- BaseCache
- abc.ABC
Class variables
var redis : aioredis.Redis
var static_ttl : int
var ttl : int
Methods
def deserialize_value(self, value: bytes) ‑> Any
-
Deserialize a value back into data.
def serialize_key(self, key: typing.Any) ‑> str
-
Serialize a key by turning it into a string.
def serialize_value(self, value: typing.Any) ‑> Union[str, bytes]
-
Serialize a value by turning it into bytes.
Inherited members
class SQLiteCache (conn: aiosqlite.Connection | None = None, *, ttl: int = 3600, static_ttl: int = 86400, db_name: str = 'genshin_py.db')
-
SQLite implementation of the cache.
Expand source code
class SQLiteCache(BaseCache): """SQLite implementation of the cache.""" conn: aiosqlite.Connection | None ttl: int static_ttl: int def __init__( self, conn: aiosqlite.Connection | None = None, *, ttl: int = HOUR, static_ttl: int = DAY, db_name: str = "genshin_py.db", ) -> None: self.conn = conn self.ttl = ttl self.static_ttl = static_ttl self.db_name = db_name async def _clear_cache(self, conn: aiosqlite.Connection) -> None: """Clear timed-out items.""" now = time.time() await conn.execute("DELETE FROM cache WHERE expiration < ?", (now,)) await conn.commit() async def initialize(self) -> None: """Initialize the cache.""" import aiosqlite if self.conn is None: conn = await aiosqlite.connect(self.db_name) else: conn = self.conn await conn.execute("CREATE TABLE IF NOT EXISTS cache (key TEXT PRIMARY KEY, value TEXT, expiration INTEGER)") await conn.commit() if self.conn is None: await conn.close() def serialize_key(self, key: typing.Any) -> str: """Serialize a key by turning it into a string.""" return str(key) def serialize_value(self, value: typing.Any) -> str: """Serialize a value by turning it into a string.""" return json.dumps(value) def deserialize_value(self, value: str) -> typing.Any: """Deserialize a value back into data.""" return json.loads(value) async def get(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get an object with a key.""" import aiosqlite if self.conn is None: conn = await aiosqlite.connect(self.db_name) else: conn = self.conn async with conn.execute( "SELECT value FROM cache WHERE key = ? AND expiration > ?", (self.serialize_key(key), int(time.time())) ) as cursor: value = await cursor.fetchone() if self.conn is None: await conn.close() if value is None: return None return self.deserialize_value(value[0]) async def set(self, key: typing.Any, value: typing.Any) -> None: """Save an object with a key.""" import aiosqlite if self.conn is None: conn = await aiosqlite.connect(self.db_name) else: conn = self.conn await conn.execute( "INSERT OR REPLACE INTO cache (key, value, expiration) VALUES (?, ?, ?)", (self.serialize_key(key), self.serialize_value(value), int(time.time() + self.ttl)), ) await conn.commit() await self._clear_cache(conn) if self.conn is None: await conn.close() async def get_static(self, key: typing.Any) -> typing.Optional[typing.Any]: """Get a static object with a key.""" return await self.get(key) async def set_static(self, key: typing.Any, value: typing.Any) -> None: """Save a static object with a key.""" import aiosqlite if self.conn is None: conn = await aiosqlite.connect(self.db_name) else: conn = self.conn await conn.execute( "INSERT OR REPLACE INTO cache (key, value, expiration) VALUES (?, ?, ?)", (self.serialize_key(key), self.serialize_value(value), int(time.time() + self.static_ttl)), ) await conn.commit() await self._clear_cache(conn) if self.conn is None: await conn.close()
Ancestors
- BaseCache
- abc.ABC
Class variables
var conn : aiosqlite.Connection | None
var static_ttl : int
var ttl : int
Methods
def deserialize_value(self, value: str) ‑> Any
-
Deserialize a value back into data.
async def initialize(self) ‑> None
-
Initialize the cache.
def serialize_key(self, key: typing.Any) ‑> str
-
Serialize a key by turning it into a string.
def serialize_value(self, value: typing.Any) ‑> str
-
Serialize a value by turning it into a string.
Inherited members
class StaticCache (ttl: float = 86400)
-
Cache for only static resources.
Expand source code
class StaticCache(Cache): """Cache for only static resources.""" def __init__(self, ttl: float = DAY) -> None: super().__init__(maxsize=sys.maxsize, ttl=0, static_ttl=ttl) async def set(self, key: typing.Any, value: typing.Any) -> None: """Do nothing."""
Ancestors
Class variables
var cache : dict[typing.Any, tuple[float, typing.Any]]
var maxsize : int
var static_ttl : float
var ttl : float
Methods
async def set(self, key: typing.Any, value: typing.Any) ‑> None
-
Do nothing.
Inherited members