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.
- {cachetools-6.1.0 → cachetools-6.2.0}/CHANGELOG.rst +10 -0
- {cachetools-6.1.0/src/cachetools.egg-info → cachetools-6.2.0}/PKG-INFO +1 -1
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/__init__.py +19 -2
- {cachetools-6.1.0 → cachetools-6.2.0/src/cachetools.egg-info}/PKG-INFO +1 -1
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_fifo.py +13 -1
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_lfu.py +12 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_lru.py +12 -0
- cachetools-6.2.0/tests/test_rr.py +83 -0
- cachetools-6.1.0/tests/test_rr.py +0 -34
- {cachetools-6.1.0 → cachetools-6.2.0}/LICENSE +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/MANIFEST.in +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/README.rst +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/docs/conf.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/docs/index.rst +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/pyproject.toml +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/setup.cfg +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/setup.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/_cached.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/_cachedmethod.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/func.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools/keys.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools.egg-info/SOURCES.txt +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools.egg-info/dependency_links.txt +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/src/cachetools.egg-info/top_level.txt +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/__init__.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_cache.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_cached.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_cachedmethod.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_func.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_keys.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_tlru.py +0 -0
- {cachetools-6.1.0 → cachetools-6.2.0}/tests/test_ttl.py +0 -0
- {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
|
|
|
@@ -12,7 +12,7 @@ __all__ = (
|
|
|
12
12
|
"cachedmethod",
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
-
__version__ = "6.
|
|
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(
|
|
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:
|
|
@@ -5,7 +5,7 @@ from cachetools import FIFOCache
|
|
|
5
5
|
from . import CacheTestMixin
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|