| import typing as _t |
|
|
|
|
| class BaseCache: |
| """Baseclass for the cache systems. All the cache systems implement this |
| API or a superset of it. |
| |
| :param default_timeout: the default timeout (in seconds) that is used if |
| no timeout is specified on :meth:`set`. A timeout |
| of 0 indicates that the cache never expires. |
| """ |
|
|
| def __init__(self, default_timeout: int = 300): |
| self.default_timeout = default_timeout |
|
|
| def _normalize_timeout(self, timeout: _t.Optional[int]) -> int: |
| if timeout is None: |
| timeout = self.default_timeout |
| return timeout |
|
|
| def get(self, key: str) -> _t.Any: |
| """Look up key in the cache and return the value for it. |
| |
| :param key: the key to be looked up. |
| :returns: The value if it exists and is readable, else ``None``. |
| """ |
| return None |
|
|
| def delete(self, key: str) -> bool: |
| """Delete `key` from the cache. |
| |
| :param key: the key to delete. |
| :returns: Whether the key existed and has been deleted. |
| :rtype: boolean |
| """ |
| return True |
|
|
| def get_many(self, *keys: str) -> _t.List[_t.Any]: |
| """Returns a list of values for the given keys. |
| For each key an item in the list is created:: |
| |
| foo, bar = cache.get_many("foo", "bar") |
| |
| Has the same error handling as :meth:`get`. |
| |
| :param keys: The function accepts multiple keys as positional |
| arguments. |
| """ |
| return [self.get(k) for k in keys] |
|
|
| def get_dict(self, *keys: str) -> _t.Dict[str, _t.Any]: |
| """Like :meth:`get_many` but return a dict:: |
| |
| d = cache.get_dict("foo", "bar") |
| foo = d["foo"] |
| bar = d["bar"] |
| |
| :param keys: The function accepts multiple keys as positional |
| arguments. |
| """ |
| return dict(zip(keys, self.get_many(*keys))) |
|
|
| def set( |
| self, key: str, value: _t.Any, timeout: _t.Optional[int] = None |
| ) -> _t.Optional[bool]: |
| """Add a new key/value to the cache (overwrites value, if key already |
| exists in the cache). |
| |
| :param key: the key to set |
| :param value: the value for the key |
| :param timeout: the cache timeout for the key in seconds (if not |
| specified, it uses the default timeout). A timeout of |
| 0 indicates that the cache never expires. |
| :returns: ``True`` if key has been updated, ``False`` for backend |
| errors. Pickling errors, however, will raise a subclass of |
| ``pickle.PickleError``. |
| :rtype: boolean |
| """ |
| return True |
|
|
| def add(self, key: str, value: _t.Any, timeout: _t.Optional[int] = None) -> bool: |
| """Works like :meth:`set` but does not overwrite the values of already |
| existing keys. |
| |
| :param key: the key to set |
| :param value: the value for the key |
| :param timeout: the cache timeout for the key in seconds (if not |
| specified, it uses the default timeout). A timeout of |
| 0 indicates that the cache never expires. |
| :returns: Same as :meth:`set`, but also ``False`` for already |
| existing keys. |
| :rtype: boolean |
| """ |
| return True |
|
|
| def set_many( |
| self, mapping: _t.Dict[str, _t.Any], timeout: _t.Optional[int] = None |
| ) -> _t.List[_t.Any]: |
| """Sets multiple keys and values from a mapping. |
| |
| :param mapping: a mapping with the keys/values to set. |
| :param timeout: the cache timeout for the key in seconds (if not |
| specified, it uses the default timeout). A timeout of |
| 0 indicates that the cache never expires. |
| :returns: A list containing all keys sucessfuly set |
| :rtype: boolean |
| """ |
| set_keys = [] |
| for key, value in mapping.items(): |
| if self.set(key, value, timeout): |
| set_keys.append(key) |
| return set_keys |
|
|
| def delete_many(self, *keys: str) -> _t.List[_t.Any]: |
| """Deletes multiple keys at once. |
| |
| :param keys: The function accepts multiple keys as positional |
| arguments. |
| :returns: A list containing all sucessfuly deleted keys |
| :rtype: boolean |
| """ |
| deleted_keys = [] |
| for key in keys: |
| if self.delete(key): |
| deleted_keys.append(key) |
| return deleted_keys |
|
|
| def has(self, key: str) -> bool: |
| """Checks if a key exists in the cache without returning it. This is a |
| cheap operation that bypasses loading the actual data on the backend. |
| |
| :param key: the key to check |
| """ |
| raise NotImplementedError( |
| "%s doesn't have an efficient implementation of `has`. That " |
| "means it is impossible to check whether a key exists without " |
| "fully loading the key's data. Consider using `self.get` " |
| "explicitly if you don't care about performance." |
| ) |
|
|
| def clear(self) -> bool: |
| """Clears the cache. Keep in mind that not all caches support |
| completely clearing the cache. |
| |
| :returns: Whether the cache has been cleared. |
| :rtype: boolean |
| """ |
| return True |
|
|
| def inc(self, key: str, delta: int = 1) -> _t.Optional[int]: |
| """Increments the value of a key by `delta`. If the key does |
| not yet exist it is initialized with `delta`. |
| |
| For supporting caches this is an atomic operation. |
| |
| :param key: the key to increment. |
| :param delta: the delta to add. |
| :returns: The new value or ``None`` for backend errors. |
| """ |
| value = (self.get(key) or 0) + delta |
| return value if self.set(key, value) else None |
|
|
| def dec(self, key: str, delta: int = 1) -> _t.Optional[int]: |
| """Decrements the value of a key by `delta`. If the key does |
| not yet exist it is initialized with `-delta`. |
| |
| For supporting caches this is an atomic operation. |
| |
| :param key: the key to increment. |
| :param delta: the delta to subtract. |
| :returns: The new value or `None` for backend errors. |
| """ |
| value = (self.get(key) or 0) - delta |
| return value if self.set(key, value) else None |
|
|
|
|
| class NullCache(BaseCache): |
| """A cache that doesn't cache. This can be useful for unit testing. |
| |
| :param default_timeout: a dummy parameter that is ignored but exists |
| for API compatibility with other caches. |
| """ |
|
|
| def has(self, key: str) -> bool: |
| return False |
|
|