base.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import typing as _t
  2. class BaseCache:
  3. """Baseclass for the cache systems. All the cache systems implement this
  4. API or a superset of it.
  5. :param default_timeout: the default timeout (in seconds) that is used if
  6. no timeout is specified on :meth:`set`. A timeout
  7. of 0 indicates that the cache never expires.
  8. """
  9. def __init__(self, default_timeout: int = 300):
  10. self.default_timeout = default_timeout
  11. def _normalize_timeout(self, timeout: _t.Optional[int]) -> int:
  12. if timeout is None:
  13. timeout = self.default_timeout
  14. return timeout
  15. def get(self, key: str) -> _t.Any:
  16. """Look up key in the cache and return the value for it.
  17. :param key: the key to be looked up.
  18. :returns: The value if it exists and is readable, else ``None``.
  19. """
  20. return None
  21. def delete(self, key: str) -> bool:
  22. """Delete `key` from the cache.
  23. :param key: the key to delete.
  24. :returns: Whether the key existed and has been deleted.
  25. :rtype: boolean
  26. """
  27. return True
  28. def get_many(self, *keys: str) -> _t.List[_t.Any]:
  29. """Returns a list of values for the given keys.
  30. For each key an item in the list is created::
  31. foo, bar = cache.get_many("foo", "bar")
  32. Has the same error handling as :meth:`get`.
  33. :param keys: The function accepts multiple keys as positional
  34. arguments.
  35. """
  36. return [self.get(k) for k in keys]
  37. def get_dict(self, *keys: str) -> _t.Dict[str, _t.Any]:
  38. """Like :meth:`get_many` but return a dict::
  39. d = cache.get_dict("foo", "bar")
  40. foo = d["foo"]
  41. bar = d["bar"]
  42. :param keys: The function accepts multiple keys as positional
  43. arguments.
  44. """
  45. return dict(zip(keys, self.get_many(*keys)))
  46. def set(
  47. self, key: str, value: _t.Any, timeout: _t.Optional[int] = None
  48. ) -> _t.Optional[bool]:
  49. """Add a new key/value to the cache (overwrites value, if key already
  50. exists in the cache).
  51. :param key: the key to set
  52. :param value: the value for the key
  53. :param timeout: the cache timeout for the key in seconds (if not
  54. specified, it uses the default timeout). A timeout of
  55. 0 indicates that the cache never expires.
  56. :returns: ``True`` if key has been updated, ``False`` for backend
  57. errors. Pickling errors, however, will raise a subclass of
  58. ``pickle.PickleError``.
  59. :rtype: boolean
  60. """
  61. return True
  62. def add(self, key: str, value: _t.Any, timeout: _t.Optional[int] = None) -> bool:
  63. """Works like :meth:`set` but does not overwrite the values of already
  64. existing keys.
  65. :param key: the key to set
  66. :param value: the value for the key
  67. :param timeout: the cache timeout for the key in seconds (if not
  68. specified, it uses the default timeout). A timeout of
  69. 0 indicates that the cache never expires.
  70. :returns: Same as :meth:`set`, but also ``False`` for already
  71. existing keys.
  72. :rtype: boolean
  73. """
  74. return True
  75. def set_many(
  76. self, mapping: _t.Dict[str, _t.Any], timeout: _t.Optional[int] = None
  77. ) -> _t.List[_t.Any]:
  78. """Sets multiple keys and values from a mapping.
  79. :param mapping: a mapping with the keys/values to set.
  80. :param timeout: the cache timeout for the key in seconds (if not
  81. specified, it uses the default timeout). A timeout of
  82. 0 indicates that the cache never expires.
  83. :returns: A list containing all keys sucessfuly set
  84. :rtype: boolean
  85. """
  86. set_keys = []
  87. for key, value in mapping.items():
  88. if self.set(key, value, timeout):
  89. set_keys.append(key)
  90. return set_keys
  91. def delete_many(self, *keys: str) -> _t.List[_t.Any]:
  92. """Deletes multiple keys at once.
  93. :param keys: The function accepts multiple keys as positional
  94. arguments.
  95. :returns: A list containing all sucessfuly deleted keys
  96. :rtype: boolean
  97. """
  98. deleted_keys = []
  99. for key in keys:
  100. if self.delete(key):
  101. deleted_keys.append(key)
  102. return deleted_keys
  103. def has(self, key: str) -> bool:
  104. """Checks if a key exists in the cache without returning it. This is a
  105. cheap operation that bypasses loading the actual data on the backend.
  106. :param key: the key to check
  107. """
  108. raise NotImplementedError(
  109. "%s doesn't have an efficient implementation of `has`. That "
  110. "means it is impossible to check whether a key exists without "
  111. "fully loading the key's data. Consider using `self.get` "
  112. "explicitly if you don't care about performance."
  113. )
  114. def clear(self) -> bool:
  115. """Clears the cache. Keep in mind that not all caches support
  116. completely clearing the cache.
  117. :returns: Whether the cache has been cleared.
  118. :rtype: boolean
  119. """
  120. return True
  121. def inc(self, key: str, delta: int = 1) -> _t.Optional[int]:
  122. """Increments the value of a key by `delta`. If the key does
  123. not yet exist it is initialized with `delta`.
  124. For supporting caches this is an atomic operation.
  125. :param key: the key to increment.
  126. :param delta: the delta to add.
  127. :returns: The new value or ``None`` for backend errors.
  128. """
  129. value = (self.get(key) or 0) + delta
  130. return value if self.set(key, value) else None
  131. def dec(self, key: str, delta: int = 1) -> _t.Optional[int]:
  132. """Decrements the value of a key by `delta`. If the key does
  133. not yet exist it is initialized with `-delta`.
  134. For supporting caches this is an atomic operation.
  135. :param key: the key to increment.
  136. :param delta: the delta to subtract.
  137. :returns: The new value or `None` for backend errors.
  138. """
  139. value = (self.get(key) or 0) - delta
  140. return value if self.set(key, value) else None
  141. class NullCache(BaseCache):
  142. """A cache that doesn't cache. This can be useful for unit testing.
  143. :param default_timeout: a dummy parameter that is ignored but exists
  144. for API compatibility with other caches.
  145. """
  146. def has(self, key: str) -> bool:
  147. return False