cachetools 6.1.0__tar.gz → 6.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. {cachetools-6.1.0 → cachetools-6.2.0}/CHANGELOG.rst +10 -0
  2. {cachetools-6.1.0/src/cachetools.egg-info → cachetools-6.2.0}/PKG-INFO +1 -1
  3. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/__init__.py +19 -2
  4. {cachetools-6.1.0 → cachetools-6.2.0/src/cachetools.egg-info}/PKG-INFO +1 -1
  5. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_fifo.py +13 -1
  6. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_lfu.py +12 -0
  7. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_lru.py +12 -0
  8. cachetools-6.2.0/tests/test_rr.py +83 -0
  9. cachetools-6.1.0/tests/test_rr.py +0 -34
  10. {cachetools-6.1.0 → cachetools-6.2.0}/LICENSE +0 -0
  11. {cachetools-6.1.0 → cachetools-6.2.0}/MANIFEST.in +0 -0
  12. {cachetools-6.1.0 → cachetools-6.2.0}/README.rst +0 -0
  13. {cachetools-6.1.0 → cachetools-6.2.0}/docs/conf.py +0 -0
  14. {cachetools-6.1.0 → cachetools-6.2.0}/docs/index.rst +0 -0
  15. {cachetools-6.1.0 → cachetools-6.2.0}/pyproject.toml +0 -0
  16. {cachetools-6.1.0 → cachetools-6.2.0}/setup.cfg +0 -0
  17. {cachetools-6.1.0 → cachetools-6.2.0}/setup.py +0 -0
  18. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/_cached.py +0 -0
  19. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/_cachedmethod.py +0 -0
  20. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/func.py +0 -0
  21. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/keys.py +0 -0
  22. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools.egg-info/SOURCES.txt +0 -0
  23. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools.egg-info/dependency_links.txt +0 -0
  24. {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools.egg-info/top_level.txt +0 -0
  25. {cachetools-6.1.0 → cachetools-6.2.0}/tests/__init__.py +0 -0
  26. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_cache.py +0 -0
  27. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_cached.py +0 -0
  28. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_cachedmethod.py +0 -0
  29. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_func.py +0 -0
  30. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_keys.py +0 -0
  31. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_tlru.py +0 -0
  32. {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_ttl.py +0 -0
  33. {cachetools-6.1.0 → cachetools-6.2.0}/tox.ini +0 -0
@@ -1,3 +1,13 @@
1
+ v6.2.0 (2025-08-25)
2
+ ===================
3
+
4
+ - Improve general ``RRCache`` performance by storing cache keys in an
5
+ additional sequence container. Note that this will increase memory
6
+ consumption.
7
+
8
+ - Add more unit tests.
9
+
10
+
1
11
  v6.1.0 (2025-06-16)
2
12
  ===================
3
13
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cachetools
3
- Version: 6.1.0
3
+ Version: 6.2.0
4
4
  Summary: Extensible memoizing collections and decorators
5
5
  Home-page: https://github.com/tkem/cachetools/
6
6
  Author: Thomas Kemmer
@@ -12,7 +12,7 @@ __all__ = (
12
12
  "cachedmethod",
13
13
  )
14
14
 
15
- __version__ = "6.1.0"
15
+ __version__ = "6.2.0"
16
16
 
17
17
  import collections
18
18
  import collections.abc
@@ -288,16 +288,33 @@ class RRCache(Cache):
288
288
  def __init__(self, maxsize, choice=random.choice, getsizeof=None):
289
289
  Cache.__init__(self, maxsize, getsizeof)
290
290
  self.__choice = choice
291
+ self.__index = {}
292
+ self.__keys = []
291
293
 
292
294
  @property
293
295
  def choice(self):
294
296
  """The `choice` function used by the cache."""
295
297
  return self.__choice
296
298
 
299
+ def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
300
+ cache_setitem(self, key, value)
301
+ if key not in self.__index:
302
+ self.__index[key] = len(self.__keys)
303
+ self.__keys.append(key)
304
+
305
+ def __delitem__(self, key, cache_delitem=Cache.__delitem__):
306
+ cache_delitem(self, key)
307
+ index = self.__index.pop(key)
308
+ if index != len(self.__keys) - 1:
309
+ last = self.__keys[-1]
310
+ self.__keys[index] = last
311
+ self.__index[last] = index
312
+ self.__keys.pop()
313
+
297
314
  def popitem(self):
298
315
  """Remove and return a random `(key, value)` pair."""
299
316
  try:
300
- key = self.__choice(list(self))
317
+ key = self.__choice(self.__keys)
301
318
  except IndexError:
302
319
  raise KeyError("%s is empty" % type(self).__name__) from None
303
320
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cachetools
3
- Version: 6.1.0
3
+ Version: 6.2.0
4
4
  Summary: Extensible memoizing collections and decorators
5
5
  Home-page: https://github.com/tkem/cachetools/
6
6
  Author: Thomas Kemmer
@@ -5,7 +5,7 @@ from cachetools import FIFOCache
5
5
  from . import CacheTestMixin
6
6
 
7
7
 
8
- class LRUCacheTest(unittest.TestCase, CacheTestMixin):
8
+ class FIFOCacheTest(unittest.TestCase, CacheTestMixin):
9
9
  Cache = FIFOCache
10
10
 
11
11
  def test_fifo(self):
@@ -54,3 +54,15 @@ class LRUCacheTest(unittest.TestCase, CacheTestMixin):
54
54
  cache[4] = 4
55
55
  self.assertEqual(len(cache), 1)
56
56
  self.assertEqual(cache[3], 3)
57
+
58
+ def test_fifo_update_existing(self):
59
+ cache = FIFOCache(maxsize=2)
60
+
61
+ cache[1] = 1
62
+ cache[2] = 2
63
+ cache[1] = "updated"
64
+ cache[3] = 3
65
+
66
+ self.assertEqual(cache[1], "updated")
67
+ self.assertIn(3, cache)
68
+ self.assertNotIn(2, cache)
@@ -52,3 +52,15 @@ class LFUCacheTest(unittest.TestCase, CacheTestMixin):
52
52
  cache[4] = 4
53
53
  self.assertEqual(len(cache), 1)
54
54
  self.assertEqual(cache[3], 3)
55
+
56
+ def test_lfu_update_existing(self):
57
+ cache = LFUCache(maxsize=2)
58
+
59
+ cache[1] = 1
60
+ cache[2] = 2
61
+ cache[1] = "updated"
62
+ cache[3] = 3
63
+
64
+ self.assertEqual(cache[1], "updated")
65
+ self.assertIn(3, cache)
66
+ self.assertNotIn(2, cache)
@@ -54,3 +54,15 @@ class LRUCacheTest(unittest.TestCase, CacheTestMixin):
54
54
  cache[4] = 4
55
55
  self.assertEqual(len(cache), 1)
56
56
  self.assertEqual(cache[3], 3)
57
+
58
+ def test_lru_update_existing(self):
59
+ cache = LRUCache(maxsize=2)
60
+
61
+ cache[1] = 1
62
+ cache[2] = 2
63
+ cache[1] = "updated"
64
+ cache[3] = 3
65
+
66
+ self.assertEqual(cache[1], "updated")
67
+ self.assertIn(3, cache)
68
+ self.assertNotIn(2, cache)
@@ -0,0 +1,83 @@
1
+ import random
2
+ import unittest
3
+
4
+ from cachetools import RRCache
5
+
6
+ from . import CacheTestMixin
7
+
8
+
9
+ class RRCacheTest(unittest.TestCase, CacheTestMixin):
10
+ Cache = RRCache
11
+
12
+ def test_rr(self):
13
+ cache = RRCache(maxsize=2, choice=min)
14
+ self.assertEqual(min, cache.choice)
15
+
16
+ cache[1] = 1
17
+ cache[2] = 2
18
+ cache[3] = 3
19
+
20
+ self.assertEqual(2, len(cache))
21
+ self.assertEqual(2, cache[2])
22
+ self.assertEqual(3, cache[3])
23
+ self.assertNotIn(1, cache)
24
+
25
+ cache[0] = 0
26
+ self.assertEqual(2, len(cache))
27
+ self.assertEqual(0, cache[0])
28
+ self.assertEqual(3, cache[3])
29
+ self.assertNotIn(2, cache)
30
+
31
+ cache[4] = 4
32
+ self.assertEqual(2, len(cache))
33
+ self.assertEqual(3, cache[3])
34
+ self.assertEqual(4, cache[4])
35
+ self.assertNotIn(0, cache)
36
+
37
+ def test_rr_getsizeof(self):
38
+ cache = RRCache(maxsize=3, choice=min, getsizeof=lambda x: x)
39
+
40
+ cache[1] = 1
41
+ cache[2] = 2
42
+
43
+ self.assertEqual(len(cache), 2)
44
+ self.assertEqual(cache[1], 1)
45
+ self.assertEqual(cache[2], 2)
46
+
47
+ cache[3] = 3
48
+
49
+ self.assertEqual(len(cache), 1)
50
+ self.assertEqual(cache[3], 3)
51
+ self.assertNotIn(1, cache)
52
+ self.assertNotIn(2, cache)
53
+
54
+ with self.assertRaises(ValueError):
55
+ cache[4] = 4
56
+ self.assertEqual(len(cache), 1)
57
+ self.assertEqual(cache[3], 3)
58
+
59
+ def test_rr_update_existing(self):
60
+ cache = RRCache(maxsize=2, choice=min)
61
+
62
+ cache[1] = 1
63
+ cache[2] = 2
64
+ cache[1] = "updated"
65
+ cache[3] = 3
66
+
67
+ self.assertIn(2, cache)
68
+ self.assertIn(3, cache)
69
+ self.assertNotIn(1, cache)
70
+
71
+ def test_rr_bad_choice(self):
72
+ def bad_choice(seq):
73
+ raise ValueError("test error")
74
+
75
+ cache = RRCache(maxsize=2, choice=bad_choice)
76
+ cache[1] = 1
77
+ cache[2] = 2
78
+ with self.assertRaises(ValueError):
79
+ cache[3] = 3
80
+
81
+ def test_rr_default_choice(self):
82
+ cache = RRCache(maxsize=2)
83
+ self.assertIs(cache.choice, random.choice)
@@ -1,34 +0,0 @@
1
- import unittest
2
-
3
- from cachetools import RRCache
4
-
5
- from . import CacheTestMixin
6
-
7
-
8
- class RRCacheTest(unittest.TestCase, CacheTestMixin):
9
- Cache = RRCache
10
-
11
- def test_rr(self):
12
- cache = RRCache(maxsize=2, choice=min)
13
- self.assertEqual(min, cache.choice)
14
-
15
- cache[1] = 1
16
- cache[2] = 2
17
- cache[3] = 3
18
-
19
- self.assertEqual(2, len(cache))
20
- self.assertEqual(2, cache[2])
21
- self.assertEqual(3, cache[3])
22
- self.assertNotIn(1, cache)
23
-
24
- cache[0] = 0
25
- self.assertEqual(2, len(cache))
26
- self.assertEqual(0, cache[0])
27
- self.assertEqual(3, cache[3])
28
- self.assertNotIn(2, cache)
29
-
30
- cache[4] = 4
31
- self.assertEqual(2, len(cache))
32
- self.assertEqual(3, cache[3])
33
- self.assertEqual(4, cache[4])
34
- self.assertNotIn(0, cache)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes