You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
2.2 KiB

  1. from .abc import DefaultMapping
  2. class _DefaultSize(object):
  3. def __getitem__(self, _):
  4. return 1
  5. def __setitem__(self, _, value):
  6. assert value == 1
  7. def pop(self, _):
  8. return 1
  9. class Cache(DefaultMapping):
  10. """Mutable mapping to serve as a simple cache or cache base class."""
  11. __size = _DefaultSize()
  12. def __init__(self, maxsize, getsizeof=None):
  13. if getsizeof:
  14. self.getsizeof = getsizeof
  15. if self.getsizeof is not Cache.getsizeof:
  16. self.__size = dict()
  17. self.__data = dict()
  18. self.__currsize = 0
  19. self.__maxsize = maxsize
  20. def __repr__(self):
  21. return '%s(%r, maxsize=%r, currsize=%r)' % (
  22. self.__class__.__name__,
  23. list(self.__data.items()),
  24. self.__maxsize,
  25. self.__currsize,
  26. )
  27. def __getitem__(self, key):
  28. try:
  29. return self.__data[key]
  30. except KeyError:
  31. return self.__missing__(key)
  32. def __setitem__(self, key, value):
  33. maxsize = self.__maxsize
  34. size = self.getsizeof(value)
  35. if size > maxsize:
  36. raise ValueError('value too large')
  37. if key not in self.__data or self.__size[key] < size:
  38. while self.__currsize + size > maxsize:
  39. self.popitem()
  40. if key in self.__data:
  41. diffsize = size - self.__size[key]
  42. else:
  43. diffsize = size
  44. self.__data[key] = value
  45. self.__size[key] = size
  46. self.__currsize += diffsize
  47. def __delitem__(self, key):
  48. size = self.__size.pop(key)
  49. del self.__data[key]
  50. self.__currsize -= size
  51. def __contains__(self, key):
  52. return key in self.__data
  53. def __missing__(self, key):
  54. raise KeyError(key)
  55. def __iter__(self):
  56. return iter(self.__data)
  57. def __len__(self):
  58. return len(self.__data)
  59. @property
  60. def maxsize(self):
  61. """The maximum size of the cache."""
  62. return self.__maxsize
  63. @property
  64. def currsize(self):
  65. """The current size of the cache."""
  66. return self.__currsize
  67. @staticmethod
  68. def getsizeof(value):
  69. """Return the size of a cache element's value."""
  70. return 1