cachetools 6.0.0b4__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.0.0b4 → cachetools-6.2.0}/CHANGELOG.rst +21 -1
- {cachetools-6.0.0b4/src/cachetools.egg-info → cachetools-6.2.0}/PKG-INFO +11 -8
- {cachetools-6.0.0b4 → cachetools-6.2.0}/README.rst +10 -7
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools/__init__.py +74 -11
- {cachetools-6.0.0b4 → cachetools-6.2.0/src/cachetools.egg-info}/PKG-INFO +11 -8
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_cachedmethod.py +128 -77
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_fifo.py +13 -1
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_func.py +5 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_lfu.py +17 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_lru.py +12 -0
- cachetools-6.2.0/tests/test_rr.py +83 -0
- cachetools-6.0.0b4/tests/test_rr.py +0 -34
- {cachetools-6.0.0b4 → cachetools-6.2.0}/LICENSE +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/MANIFEST.in +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/docs/conf.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/docs/index.rst +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/pyproject.toml +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/setup.cfg +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/setup.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools/_cached.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools/_cachedmethod.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools/func.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools/keys.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools.egg-info/SOURCES.txt +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools.egg-info/dependency_links.txt +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/src/cachetools.egg-info/top_level.txt +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/__init__.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_cache.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_cached.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_keys.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_tlru.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tests/test_ttl.py +0 -0
- {cachetools-6.0.0b4 → cachetools-6.2.0}/tox.ini +0 -0
|
@@ -1,4 +1,24 @@
|
|
|
1
|
-
v6.
|
|
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
|
+
|
|
11
|
+
v6.1.0 (2025-06-16)
|
|
12
|
+
===================
|
|
13
|
+
|
|
14
|
+
- Improve ``LFUCache`` insertion performance by switching to an
|
|
15
|
+
implementation based on the `cacheing
|
|
16
|
+
<https://pypi.org/project/cacheing/>`_ library.
|
|
17
|
+
|
|
18
|
+
- Update CI environment.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
v6.0.0 (2025-05-23)
|
|
2
22
|
===================
|
|
3
23
|
|
|
4
24
|
- Require Python 3.9 or later (breaking change).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachetools
|
|
3
|
-
Version: 6.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
|
|
@@ -115,11 +115,12 @@ Project Resources
|
|
|
115
115
|
Related Projects
|
|
116
116
|
------------------------------------------------------------------------
|
|
117
117
|
|
|
118
|
-
- asyncache_: Helpers to use
|
|
119
|
-
- cacheing_: Pure Python Cacheing Library
|
|
120
|
-
- CacheToolsUtils_:
|
|
121
|
-
|
|
122
|
-
- shelved-cache_: Persistent cache for Python
|
|
118
|
+
- asyncache_: Helpers to use cachetools_ with asyncio.
|
|
119
|
+
- cacheing_: Pure Python Cacheing Library.
|
|
120
|
+
- CacheToolsUtils_: Stackable cache classes for sharing, encryption,
|
|
121
|
+
statistics *and more* on top of cachetools_, redis_ and memcached_.
|
|
122
|
+
- shelved-cache_: Persistent cache implementation for Python
|
|
123
|
+
cachetools_.
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
License
|
|
@@ -144,7 +145,9 @@ Licensed under the `MIT License`_.
|
|
|
144
145
|
.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE
|
|
145
146
|
|
|
146
147
|
.. _asyncache: https://pypi.org/project/asyncache/
|
|
147
|
-
.. _cacheing: https://
|
|
148
|
+
.. _cacheing: https://pypi.org/project/cacheing/
|
|
148
149
|
.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/
|
|
149
|
-
.. _kids.cache: https://pypi.org/project/kids.cache/
|
|
150
150
|
.. _shelved-cache: https://pypi.org/project/shelved-cache/
|
|
151
|
+
.. _cachetools: https://pypi.org/project/cachetools/
|
|
152
|
+
.. _redis: https://redis.io/
|
|
153
|
+
.. _memcached: https://memcached.org/
|
|
@@ -90,11 +90,12 @@ Project Resources
|
|
|
90
90
|
Related Projects
|
|
91
91
|
------------------------------------------------------------------------
|
|
92
92
|
|
|
93
|
-
- asyncache_: Helpers to use
|
|
94
|
-
- cacheing_: Pure Python Cacheing Library
|
|
95
|
-
- CacheToolsUtils_:
|
|
96
|
-
|
|
97
|
-
- shelved-cache_: Persistent cache for Python
|
|
93
|
+
- asyncache_: Helpers to use cachetools_ with asyncio.
|
|
94
|
+
- cacheing_: Pure Python Cacheing Library.
|
|
95
|
+
- CacheToolsUtils_: Stackable cache classes for sharing, encryption,
|
|
96
|
+
statistics *and more* on top of cachetools_, redis_ and memcached_.
|
|
97
|
+
- shelved-cache_: Persistent cache implementation for Python
|
|
98
|
+
cachetools_.
|
|
98
99
|
|
|
99
100
|
|
|
100
101
|
License
|
|
@@ -119,7 +120,9 @@ Licensed under the `MIT License`_.
|
|
|
119
120
|
.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE
|
|
120
121
|
|
|
121
122
|
.. _asyncache: https://pypi.org/project/asyncache/
|
|
122
|
-
.. _cacheing: https://
|
|
123
|
+
.. _cacheing: https://pypi.org/project/cacheing/
|
|
123
124
|
.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/
|
|
124
|
-
.. _kids.cache: https://pypi.org/project/kids.cache/
|
|
125
125
|
.. _shelved-cache: https://pypi.org/project/shelved-cache/
|
|
126
|
+
.. _cachetools: https://pypi.org/project/cachetools/
|
|
127
|
+
.. _redis: https://redis.io/
|
|
128
|
+
.. _memcached: https://memcached.org/
|
|
@@ -12,7 +12,7 @@ __all__ = (
|
|
|
12
12
|
"cachedmethod",
|
|
13
13
|
)
|
|
14
14
|
|
|
15
|
-
__version__ = "6.0
|
|
15
|
+
__version__ = "6.2.0"
|
|
16
16
|
|
|
17
17
|
import collections
|
|
18
18
|
import collections.abc
|
|
@@ -170,32 +170,78 @@ class FIFOCache(Cache):
|
|
|
170
170
|
class LFUCache(Cache):
|
|
171
171
|
"""Least Frequently Used (LFU) cache implementation."""
|
|
172
172
|
|
|
173
|
+
class _Link:
|
|
174
|
+
__slots__ = ("count", "keys", "next", "prev")
|
|
175
|
+
|
|
176
|
+
def __init__(self, count):
|
|
177
|
+
self.count = count
|
|
178
|
+
self.keys = set()
|
|
179
|
+
|
|
180
|
+
def unlink(self):
|
|
181
|
+
next = self.next
|
|
182
|
+
prev = self.prev
|
|
183
|
+
prev.next = next
|
|
184
|
+
next.prev = prev
|
|
185
|
+
|
|
173
186
|
def __init__(self, maxsize, getsizeof=None):
|
|
174
187
|
Cache.__init__(self, maxsize, getsizeof)
|
|
175
|
-
self.
|
|
188
|
+
self.__root = root = LFUCache._Link(0) # sentinel
|
|
189
|
+
root.prev = root.next = root
|
|
190
|
+
self.__links = {}
|
|
176
191
|
|
|
177
192
|
def __getitem__(self, key, cache_getitem=Cache.__getitem__):
|
|
178
193
|
value = cache_getitem(self, key)
|
|
179
194
|
if key in self: # __missing__ may not store item
|
|
180
|
-
self.
|
|
195
|
+
self.__touch(key)
|
|
181
196
|
return value
|
|
182
197
|
|
|
183
198
|
def __setitem__(self, key, value, cache_setitem=Cache.__setitem__):
|
|
184
199
|
cache_setitem(self, key, value)
|
|
185
|
-
|
|
200
|
+
if key in self.__links:
|
|
201
|
+
return self.__touch(key)
|
|
202
|
+
root = self.__root
|
|
203
|
+
link = root.next
|
|
204
|
+
if link.count != 1:
|
|
205
|
+
link = LFUCache._Link(1)
|
|
206
|
+
link.next = root.next
|
|
207
|
+
root.next = link.next.prev = link
|
|
208
|
+
link.prev = root
|
|
209
|
+
link.keys.add(key)
|
|
210
|
+
self.__links[key] = link
|
|
186
211
|
|
|
187
212
|
def __delitem__(self, key, cache_delitem=Cache.__delitem__):
|
|
188
213
|
cache_delitem(self, key)
|
|
189
|
-
|
|
214
|
+
link = self.__links.pop(key)
|
|
215
|
+
link.keys.remove(key)
|
|
216
|
+
if not link.keys:
|
|
217
|
+
link.unlink()
|
|
190
218
|
|
|
191
219
|
def popitem(self):
|
|
192
220
|
"""Remove and return the `(key, value)` pair least frequently used."""
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
221
|
+
root = self.__root
|
|
222
|
+
curr = root.next
|
|
223
|
+
if curr is root:
|
|
196
224
|
raise KeyError("%s is empty" % type(self).__name__) from None
|
|
197
|
-
|
|
198
|
-
|
|
225
|
+
key = next(iter(curr.keys)) # remove an arbitrary element
|
|
226
|
+
return (key, self.pop(key))
|
|
227
|
+
|
|
228
|
+
def __touch(self, key):
|
|
229
|
+
"""Increment use count"""
|
|
230
|
+
link = self.__links[key]
|
|
231
|
+
curr = link.next
|
|
232
|
+
if curr.count != link.count + 1:
|
|
233
|
+
if len(link.keys) == 1:
|
|
234
|
+
link.count += 1
|
|
235
|
+
return
|
|
236
|
+
curr = LFUCache._Link(link.count + 1)
|
|
237
|
+
curr.next = link.next
|
|
238
|
+
link.next = curr.next.prev = curr
|
|
239
|
+
curr.prev = link
|
|
240
|
+
curr.keys.add(key)
|
|
241
|
+
link.keys.remove(key)
|
|
242
|
+
if not link.keys:
|
|
243
|
+
link.unlink()
|
|
244
|
+
self.__links[key] = curr
|
|
199
245
|
|
|
200
246
|
|
|
201
247
|
class LRUCache(Cache):
|
|
@@ -242,16 +288,33 @@ class RRCache(Cache):
|
|
|
242
288
|
def __init__(self, maxsize, choice=random.choice, getsizeof=None):
|
|
243
289
|
Cache.__init__(self, maxsize, getsizeof)
|
|
244
290
|
self.__choice = choice
|
|
291
|
+
self.__index = {}
|
|
292
|
+
self.__keys = []
|
|
245
293
|
|
|
246
294
|
@property
|
|
247
295
|
def choice(self):
|
|
248
296
|
"""The `choice` function used by the cache."""
|
|
249
297
|
return self.__choice
|
|
250
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
|
+
|
|
251
314
|
def popitem(self):
|
|
252
315
|
"""Remove and return a random `(key, value)` pair."""
|
|
253
316
|
try:
|
|
254
|
-
key = self.__choice(
|
|
317
|
+
key = self.__choice(self.__keys)
|
|
255
318
|
except IndexError:
|
|
256
319
|
raise KeyError("%s is empty" % type(self).__name__) from None
|
|
257
320
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cachetools
|
|
3
|
-
Version: 6.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
|
|
@@ -115,11 +115,12 @@ Project Resources
|
|
|
115
115
|
Related Projects
|
|
116
116
|
------------------------------------------------------------------------
|
|
117
117
|
|
|
118
|
-
- asyncache_: Helpers to use
|
|
119
|
-
- cacheing_: Pure Python Cacheing Library
|
|
120
|
-
- CacheToolsUtils_:
|
|
121
|
-
|
|
122
|
-
- shelved-cache_: Persistent cache for Python
|
|
118
|
+
- asyncache_: Helpers to use cachetools_ with asyncio.
|
|
119
|
+
- cacheing_: Pure Python Cacheing Library.
|
|
120
|
+
- CacheToolsUtils_: Stackable cache classes for sharing, encryption,
|
|
121
|
+
statistics *and more* on top of cachetools_, redis_ and memcached_.
|
|
122
|
+
- shelved-cache_: Persistent cache implementation for Python
|
|
123
|
+
cachetools_.
|
|
123
124
|
|
|
124
125
|
|
|
125
126
|
License
|
|
@@ -144,7 +145,9 @@ Licensed under the `MIT License`_.
|
|
|
144
145
|
.. _MIT License: https://raw.github.com/tkem/cachetools/master/LICENSE
|
|
145
146
|
|
|
146
147
|
.. _asyncache: https://pypi.org/project/asyncache/
|
|
147
|
-
.. _cacheing: https://
|
|
148
|
+
.. _cacheing: https://pypi.org/project/cacheing/
|
|
148
149
|
.. _CacheToolsUtils: https://pypi.org/project/CacheToolsUtils/
|
|
149
|
-
.. _kids.cache: https://pypi.org/project/kids.cache/
|
|
150
150
|
.. _shelved-cache: https://pypi.org/project/shelved-cache/
|
|
151
|
+
.. _cachetools: https://pypi.org/project/cachetools/
|
|
152
|
+
.. _redis: https://redis.io/
|
|
153
|
+
.. _memcached: https://memcached.org/
|
|
@@ -6,21 +6,35 @@ from cachetools import LRUCache, cachedmethod, keys
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class Cached:
|
|
9
|
+
|
|
10
|
+
class_cache = LRUCache(2)
|
|
11
|
+
class_count = 0
|
|
12
|
+
|
|
9
13
|
def __init__(self, cache, count=0):
|
|
10
14
|
self.cache = cache
|
|
11
15
|
self.count = count
|
|
12
16
|
|
|
13
17
|
@cachedmethod(lambda self: self.cache)
|
|
14
18
|
def get(self, value):
|
|
15
|
-
count = self.count
|
|
16
19
|
self.count += 1
|
|
17
|
-
return count
|
|
20
|
+
return self.count
|
|
18
21
|
|
|
19
22
|
@cachedmethod(lambda self: self.cache, key=keys.typedmethodkey)
|
|
20
23
|
def get_typedmethod(self, value):
|
|
21
|
-
count = self.count
|
|
22
24
|
self.count += 1
|
|
23
|
-
return count
|
|
25
|
+
return self.count
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
@cachedmethod(lambda cls: cls.class_cache)
|
|
29
|
+
def get_classmethod(cls, value):
|
|
30
|
+
cls.class_count += 1
|
|
31
|
+
return cls.class_count
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
@cachedmethod(lambda cls: cls.class_cache, key=keys.typedmethodkey)
|
|
35
|
+
def get_typedclassmethod(cls, value):
|
|
36
|
+
cls.class_count += 1
|
|
37
|
+
return cls.class_count
|
|
24
38
|
|
|
25
39
|
|
|
26
40
|
class Locked:
|
|
@@ -31,9 +45,8 @@ class Locked:
|
|
|
31
45
|
|
|
32
46
|
@cachedmethod(lambda self: self.cache, lock=lambda self: self)
|
|
33
47
|
def get(self, value):
|
|
34
|
-
count = self.count
|
|
35
48
|
self.count += 1
|
|
36
|
-
return count
|
|
49
|
+
return self.count
|
|
37
50
|
|
|
38
51
|
def __enter__(self):
|
|
39
52
|
self.lock_count += 1
|
|
@@ -86,57 +99,57 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
86
99
|
def test_dict(self):
|
|
87
100
|
cached = Cached({})
|
|
88
101
|
|
|
89
|
-
self.assertEqual(cached.get(0),
|
|
90
|
-
self.assertEqual(cached.get(1),
|
|
91
|
-
self.assertEqual(cached.get(1),
|
|
92
|
-
self.assertEqual(cached.get(1.0),
|
|
93
|
-
self.assertEqual(cached.get(1.0),
|
|
102
|
+
self.assertEqual(cached.get(0), 1)
|
|
103
|
+
self.assertEqual(cached.get(1), 2)
|
|
104
|
+
self.assertEqual(cached.get(1), 2)
|
|
105
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
106
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
94
107
|
|
|
95
108
|
cached.cache.clear()
|
|
96
|
-
self.assertEqual(cached.get(1),
|
|
109
|
+
self.assertEqual(cached.get(1), 3)
|
|
97
110
|
|
|
98
111
|
def test_typedmethod_dict(self):
|
|
99
112
|
cached = Cached(LRUCache(maxsize=2))
|
|
100
113
|
|
|
101
|
-
self.assertEqual(cached.get_typedmethod(0),
|
|
102
|
-
self.assertEqual(cached.get_typedmethod(1),
|
|
103
|
-
self.assertEqual(cached.get_typedmethod(1),
|
|
104
|
-
self.assertEqual(cached.get_typedmethod(1.0),
|
|
105
|
-
self.assertEqual(cached.get_typedmethod(1.0),
|
|
106
|
-
self.assertEqual(cached.get_typedmethod(0.0),
|
|
107
|
-
self.assertEqual(cached.get_typedmethod(0),
|
|
114
|
+
self.assertEqual(cached.get_typedmethod(0), 1)
|
|
115
|
+
self.assertEqual(cached.get_typedmethod(1), 2)
|
|
116
|
+
self.assertEqual(cached.get_typedmethod(1), 2)
|
|
117
|
+
self.assertEqual(cached.get_typedmethod(1.0), 3)
|
|
118
|
+
self.assertEqual(cached.get_typedmethod(1.0), 3)
|
|
119
|
+
self.assertEqual(cached.get_typedmethod(0.0), 4)
|
|
120
|
+
self.assertEqual(cached.get_typedmethod(0), 5)
|
|
108
121
|
|
|
109
122
|
def test_lru(self):
|
|
110
123
|
cached = Cached(LRUCache(maxsize=2))
|
|
111
124
|
|
|
112
|
-
self.assertEqual(cached.get(0),
|
|
113
|
-
self.assertEqual(cached.get(1),
|
|
114
|
-
self.assertEqual(cached.get(1),
|
|
115
|
-
self.assertEqual(cached.get(1.0),
|
|
116
|
-
self.assertEqual(cached.get(1.0),
|
|
125
|
+
self.assertEqual(cached.get(0), 1)
|
|
126
|
+
self.assertEqual(cached.get(1), 2)
|
|
127
|
+
self.assertEqual(cached.get(1), 2)
|
|
128
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
129
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
117
130
|
|
|
118
131
|
cached.cache.clear()
|
|
119
|
-
self.assertEqual(cached.get(1),
|
|
132
|
+
self.assertEqual(cached.get(1), 3)
|
|
120
133
|
|
|
121
134
|
def test_typedmethod_lru(self):
|
|
122
135
|
cached = Cached(LRUCache(maxsize=2))
|
|
123
136
|
|
|
124
|
-
self.assertEqual(cached.get_typedmethod(0),
|
|
125
|
-
self.assertEqual(cached.get_typedmethod(1),
|
|
126
|
-
self.assertEqual(cached.get_typedmethod(1),
|
|
127
|
-
self.assertEqual(cached.get_typedmethod(1.0),
|
|
128
|
-
self.assertEqual(cached.get_typedmethod(1.0),
|
|
129
|
-
self.assertEqual(cached.get_typedmethod(0.0),
|
|
130
|
-
self.assertEqual(cached.get_typedmethod(0),
|
|
137
|
+
self.assertEqual(cached.get_typedmethod(0), 1)
|
|
138
|
+
self.assertEqual(cached.get_typedmethod(1), 2)
|
|
139
|
+
self.assertEqual(cached.get_typedmethod(1), 2)
|
|
140
|
+
self.assertEqual(cached.get_typedmethod(1.0), 3)
|
|
141
|
+
self.assertEqual(cached.get_typedmethod(1.0), 3)
|
|
142
|
+
self.assertEqual(cached.get_typedmethod(0.0), 4)
|
|
143
|
+
self.assertEqual(cached.get_typedmethod(0), 5)
|
|
131
144
|
|
|
132
145
|
def test_nospace(self):
|
|
133
146
|
cached = Cached(LRUCache(maxsize=0))
|
|
134
147
|
|
|
135
|
-
self.assertEqual(cached.get(0),
|
|
136
|
-
self.assertEqual(cached.get(1), 1)
|
|
148
|
+
self.assertEqual(cached.get(0), 1)
|
|
137
149
|
self.assertEqual(cached.get(1), 2)
|
|
138
|
-
self.assertEqual(cached.get(1
|
|
150
|
+
self.assertEqual(cached.get(1), 3)
|
|
139
151
|
self.assertEqual(cached.get(1.0), 4)
|
|
152
|
+
self.assertEqual(cached.get(1.0), 5)
|
|
140
153
|
|
|
141
154
|
def test_nocache(self):
|
|
142
155
|
cached = Cached(None)
|
|
@@ -144,11 +157,11 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
144
157
|
with warnings.catch_warnings(record=True) as w:
|
|
145
158
|
warnings.simplefilter("always")
|
|
146
159
|
|
|
147
|
-
self.assertEqual(cached.get(0),
|
|
148
|
-
self.assertEqual(cached.get(1), 1)
|
|
160
|
+
self.assertEqual(cached.get(0), 1)
|
|
149
161
|
self.assertEqual(cached.get(1), 2)
|
|
150
|
-
self.assertEqual(cached.get(1
|
|
162
|
+
self.assertEqual(cached.get(1), 3)
|
|
151
163
|
self.assertEqual(cached.get(1.0), 4)
|
|
164
|
+
self.assertEqual(cached.get(1.0), 5)
|
|
152
165
|
|
|
153
166
|
self.assertEqual(len(w), 5)
|
|
154
167
|
self.assertIs(w[0].category, DeprecationWarning)
|
|
@@ -166,7 +179,7 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
166
179
|
|
|
167
180
|
cached = Cached(weakref.WeakValueDictionary(), count=Int(0))
|
|
168
181
|
|
|
169
|
-
self.assertEqual(cached.get(0),
|
|
182
|
+
self.assertEqual(cached.get(0), 1)
|
|
170
183
|
gc.collect()
|
|
171
184
|
self.assertEqual(cached.get(0), 1)
|
|
172
185
|
|
|
@@ -175,44 +188,44 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
175
188
|
self.assertEqual(cached.get(1), 2)
|
|
176
189
|
self.assertEqual(cached.get(1.0), 2)
|
|
177
190
|
|
|
178
|
-
ref = cached.get_typedmethod(
|
|
191
|
+
ref = cached.get_typedmethod(2)
|
|
179
192
|
self.assertEqual(ref, 3)
|
|
180
|
-
self.assertEqual(cached.get_typedmethod(1),
|
|
181
|
-
self.assertEqual(cached.get_typedmethod(1.0),
|
|
193
|
+
self.assertEqual(cached.get_typedmethod(1), 4)
|
|
194
|
+
self.assertEqual(cached.get_typedmethod(1.0), 5)
|
|
182
195
|
|
|
183
196
|
cached.cache.clear()
|
|
184
|
-
self.assertEqual(cached.get(1),
|
|
197
|
+
self.assertEqual(cached.get(1), 6)
|
|
185
198
|
|
|
186
199
|
def test_locked_dict(self):
|
|
187
200
|
cached = Locked({})
|
|
188
201
|
|
|
189
|
-
self.assertEqual(cached.get(0),
|
|
202
|
+
self.assertEqual(cached.get(0), 1)
|
|
190
203
|
self.assertEqual(cached.lock_count, 2)
|
|
191
|
-
self.assertEqual(cached.get(1),
|
|
204
|
+
self.assertEqual(cached.get(1), 2)
|
|
192
205
|
self.assertEqual(cached.lock_count, 4)
|
|
193
|
-
self.assertEqual(cached.get(1),
|
|
206
|
+
self.assertEqual(cached.get(1), 2)
|
|
194
207
|
self.assertEqual(cached.lock_count, 5)
|
|
195
|
-
self.assertEqual(cached.get(1.0),
|
|
208
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
196
209
|
self.assertEqual(cached.lock_count, 6)
|
|
197
|
-
self.assertEqual(cached.get(1.0),
|
|
210
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
198
211
|
self.assertEqual(cached.lock_count, 7)
|
|
199
212
|
|
|
200
213
|
cached.cache.clear()
|
|
201
|
-
self.assertEqual(cached.get(1),
|
|
214
|
+
self.assertEqual(cached.get(1), 3)
|
|
202
215
|
self.assertEqual(cached.lock_count, 9)
|
|
203
216
|
|
|
204
217
|
def test_locked_nospace(self):
|
|
205
218
|
cached = Locked(LRUCache(maxsize=0))
|
|
206
219
|
|
|
207
|
-
self.assertEqual(cached.get(0),
|
|
220
|
+
self.assertEqual(cached.get(0), 1)
|
|
208
221
|
self.assertEqual(cached.lock_count, 2)
|
|
209
|
-
self.assertEqual(cached.get(1), 1)
|
|
210
|
-
self.assertEqual(cached.lock_count, 4)
|
|
211
222
|
self.assertEqual(cached.get(1), 2)
|
|
223
|
+
self.assertEqual(cached.lock_count, 4)
|
|
224
|
+
self.assertEqual(cached.get(1), 3)
|
|
212
225
|
self.assertEqual(cached.lock_count, 6)
|
|
213
|
-
self.assertEqual(cached.get(1.0), 3)
|
|
214
|
-
self.assertEqual(cached.lock_count, 8)
|
|
215
226
|
self.assertEqual(cached.get(1.0), 4)
|
|
227
|
+
self.assertEqual(cached.lock_count, 8)
|
|
228
|
+
self.assertEqual(cached.get(1.0), 5)
|
|
216
229
|
self.assertEqual(cached.lock_count, 10)
|
|
217
230
|
|
|
218
231
|
def test_locked_nocache(self):
|
|
@@ -221,11 +234,11 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
221
234
|
with warnings.catch_warnings(record=True) as w:
|
|
222
235
|
warnings.simplefilter("always")
|
|
223
236
|
|
|
224
|
-
self.assertEqual(cached.get(0),
|
|
225
|
-
self.assertEqual(cached.get(1), 1)
|
|
237
|
+
self.assertEqual(cached.get(0), 1)
|
|
226
238
|
self.assertEqual(cached.get(1), 2)
|
|
227
|
-
self.assertEqual(cached.get(1
|
|
239
|
+
self.assertEqual(cached.get(1), 3)
|
|
228
240
|
self.assertEqual(cached.get(1.0), 4)
|
|
241
|
+
self.assertEqual(cached.get(1.0), 5)
|
|
229
242
|
self.assertEqual(cached.lock_count, 0)
|
|
230
243
|
|
|
231
244
|
self.assertEqual(len(w), 5)
|
|
@@ -234,29 +247,29 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
234
247
|
def test_condition_dict(self):
|
|
235
248
|
cached = Conditioned({})
|
|
236
249
|
|
|
237
|
-
self.assertEqual(cached.get(0),
|
|
250
|
+
self.assertEqual(cached.get(0), 1)
|
|
238
251
|
self.assertEqual(cached.lock_count, 3)
|
|
239
252
|
self.assertEqual(cached.wait_count, 1)
|
|
240
253
|
self.assertEqual(cached.notify_count, 1)
|
|
241
|
-
self.assertEqual(cached.get(1),
|
|
254
|
+
self.assertEqual(cached.get(1), 2)
|
|
242
255
|
self.assertEqual(cached.lock_count, 6)
|
|
243
256
|
self.assertEqual(cached.wait_count, 2)
|
|
244
257
|
self.assertEqual(cached.notify_count, 2)
|
|
245
|
-
self.assertEqual(cached.get(1),
|
|
258
|
+
self.assertEqual(cached.get(1), 2)
|
|
246
259
|
self.assertEqual(cached.lock_count, 7)
|
|
247
260
|
self.assertEqual(cached.wait_count, 3)
|
|
248
261
|
self.assertEqual(cached.notify_count, 2)
|
|
249
|
-
self.assertEqual(cached.get(1.0),
|
|
262
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
250
263
|
self.assertEqual(cached.lock_count, 8)
|
|
251
264
|
self.assertEqual(cached.wait_count, 4)
|
|
252
265
|
self.assertEqual(cached.notify_count, 2)
|
|
253
|
-
self.assertEqual(cached.get(1.0),
|
|
266
|
+
self.assertEqual(cached.get(1.0), 2)
|
|
254
267
|
self.assertEqual(cached.lock_count, 9)
|
|
255
268
|
self.assertEqual(cached.wait_count, 5)
|
|
256
269
|
self.assertEqual(cached.notify_count, 2)
|
|
257
270
|
|
|
258
271
|
cached.cache.clear()
|
|
259
|
-
self.assertEqual(cached.get(1),
|
|
272
|
+
self.assertEqual(cached.get(1), 3)
|
|
260
273
|
self.assertEqual(cached.lock_count, 12)
|
|
261
274
|
self.assertEqual(cached.wait_count, 6)
|
|
262
275
|
self.assertEqual(cached.notify_count, 3)
|
|
@@ -264,23 +277,23 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
264
277
|
def test_condition_nospace(self):
|
|
265
278
|
cached = Conditioned(LRUCache(maxsize=0))
|
|
266
279
|
|
|
267
|
-
self.assertEqual(cached.get(0),
|
|
280
|
+
self.assertEqual(cached.get(0), 1)
|
|
268
281
|
self.assertEqual(cached.lock_count, 3)
|
|
269
282
|
self.assertEqual(cached.wait_count, 1)
|
|
270
283
|
self.assertEqual(cached.notify_count, 1)
|
|
271
|
-
self.assertEqual(cached.get(1),
|
|
284
|
+
self.assertEqual(cached.get(1), 2)
|
|
272
285
|
self.assertEqual(cached.lock_count, 6)
|
|
273
286
|
self.assertEqual(cached.wait_count, 2)
|
|
274
287
|
self.assertEqual(cached.notify_count, 2)
|
|
275
|
-
self.assertEqual(cached.get(1),
|
|
288
|
+
self.assertEqual(cached.get(1), 3)
|
|
276
289
|
self.assertEqual(cached.lock_count, 9)
|
|
277
290
|
self.assertEqual(cached.wait_count, 3)
|
|
278
291
|
self.assertEqual(cached.notify_count, 3)
|
|
279
|
-
self.assertEqual(cached.get(1.0),
|
|
292
|
+
self.assertEqual(cached.get(1.0), 4)
|
|
280
293
|
self.assertEqual(cached.lock_count, 12)
|
|
281
294
|
self.assertEqual(cached.wait_count, 4)
|
|
282
295
|
self.assertEqual(cached.notify_count, 4)
|
|
283
|
-
self.assertEqual(cached.get(1.0),
|
|
296
|
+
self.assertEqual(cached.get(1.0), 5)
|
|
284
297
|
self.assertEqual(cached.lock_count, 15)
|
|
285
298
|
self.assertEqual(cached.wait_count, 5)
|
|
286
299
|
self.assertEqual(cached.notify_count, 5)
|
|
@@ -291,11 +304,11 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
291
304
|
with warnings.catch_warnings(record=True) as w:
|
|
292
305
|
warnings.simplefilter("always")
|
|
293
306
|
|
|
294
|
-
self.assertEqual(cached.get(0),
|
|
295
|
-
self.assertEqual(cached.get(1), 1)
|
|
307
|
+
self.assertEqual(cached.get(0), 1)
|
|
296
308
|
self.assertEqual(cached.get(1), 2)
|
|
297
|
-
self.assertEqual(cached.get(1
|
|
309
|
+
self.assertEqual(cached.get(1), 3)
|
|
298
310
|
self.assertEqual(cached.get(1.0), 4)
|
|
311
|
+
self.assertEqual(cached.get(1.0), 5)
|
|
299
312
|
self.assertEqual(cached.lock_count, 0)
|
|
300
313
|
self.assertEqual(cached.wait_count, 0)
|
|
301
314
|
self.assertEqual(cached.notify_count, 0)
|
|
@@ -317,11 +330,11 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
317
330
|
cached = Cached(cache)
|
|
318
331
|
|
|
319
332
|
self.assertEqual(len(cache), 0)
|
|
320
|
-
self.assertEqual(Cached.get.__wrapped__(cached, 0),
|
|
333
|
+
self.assertEqual(Cached.get.__wrapped__(cached, 0), 1)
|
|
321
334
|
self.assertEqual(len(cache), 0)
|
|
322
|
-
self.assertEqual(cached.get(0),
|
|
335
|
+
self.assertEqual(cached.get(0), 2)
|
|
323
336
|
self.assertEqual(len(cache), 1)
|
|
324
|
-
self.assertEqual(cached.get(0),
|
|
337
|
+
self.assertEqual(cached.get(0), 2)
|
|
325
338
|
self.assertEqual(len(cache), 1)
|
|
326
339
|
|
|
327
340
|
def test_attributes(self):
|
|
@@ -355,7 +368,7 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
355
368
|
cache = {}
|
|
356
369
|
cached = Cached(cache)
|
|
357
370
|
|
|
358
|
-
self.assertEqual(cached.get(0),
|
|
371
|
+
self.assertEqual(cached.get(0), 1)
|
|
359
372
|
self.assertEqual(len(cache), 1)
|
|
360
373
|
Cached.get.cache_clear(cached)
|
|
361
374
|
self.assertEqual(len(cache), 0)
|
|
@@ -364,7 +377,7 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
364
377
|
cache = {}
|
|
365
378
|
cached = Locked(cache)
|
|
366
379
|
|
|
367
|
-
self.assertEqual(cached.get(0),
|
|
380
|
+
self.assertEqual(cached.get(0), 1)
|
|
368
381
|
self.assertEqual(len(cache), 1)
|
|
369
382
|
self.assertEqual(cached.lock_count, 2)
|
|
370
383
|
Locked.get.cache_clear(cached)
|
|
@@ -375,9 +388,47 @@ class CachedMethodTest(unittest.TestCase):
|
|
|
375
388
|
cache = {}
|
|
376
389
|
cached = Conditioned(cache)
|
|
377
390
|
|
|
378
|
-
self.assertEqual(cached.get(0),
|
|
391
|
+
self.assertEqual(cached.get(0), 1)
|
|
379
392
|
self.assertEqual(len(cache), 1)
|
|
380
393
|
self.assertEqual(cached.lock_count, 3)
|
|
381
394
|
Conditioned.get.cache_clear(cached)
|
|
382
395
|
self.assertEqual(len(cache), 0)
|
|
383
396
|
self.assertEqual(cached.lock_count, 4)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
class CachedClassMethodTest(unittest.TestCase):
|
|
400
|
+
|
|
401
|
+
def test(self):
|
|
402
|
+
Cached.class_cache = LRUCache(2)
|
|
403
|
+
Cached.class_count = 0
|
|
404
|
+
cached = Cached(None)
|
|
405
|
+
|
|
406
|
+
self.assertEqual(cached.get_classmethod(0), 1)
|
|
407
|
+
self.assertEqual(Cached.get_classmethod(0), 1)
|
|
408
|
+
self.assertEqual(cached.get_classmethod(1), 2)
|
|
409
|
+
self.assertEqual(Cached.get_classmethod(1), 2)
|
|
410
|
+
self.assertEqual(cached.get_classmethod(1), 2)
|
|
411
|
+
self.assertEqual(Cached.get_classmethod(1), 2)
|
|
412
|
+
self.assertEqual(cached.get_classmethod(1.0), 2)
|
|
413
|
+
self.assertEqual(Cached.get_classmethod(1.0), 2)
|
|
414
|
+
self.assertEqual(Cached.get_classmethod(1.1), 3)
|
|
415
|
+
self.assertEqual(cached.get_classmethod(1.1), 3)
|
|
416
|
+
|
|
417
|
+
cached.class_cache.clear()
|
|
418
|
+
self.assertEqual(cached.get_classmethod(1), 4)
|
|
419
|
+
|
|
420
|
+
def test_typedmethod(self):
|
|
421
|
+
Cached.class_cache = LRUCache(2)
|
|
422
|
+
Cached.class_count = 0
|
|
423
|
+
cached = Cached(None)
|
|
424
|
+
|
|
425
|
+
self.assertEqual(cached.get_typedclassmethod(0), 1)
|
|
426
|
+
self.assertEqual(Cached.get_typedclassmethod(0), 1)
|
|
427
|
+
self.assertEqual(cached.get_typedclassmethod(1), 2)
|
|
428
|
+
self.assertEqual(Cached.get_typedclassmethod(1), 2)
|
|
429
|
+
self.assertEqual(cached.get_typedclassmethod(1.0), 3)
|
|
430
|
+
self.assertEqual(Cached.get_typedclassmethod(1.0), 3)
|
|
431
|
+
self.assertEqual(cached.get_typedclassmethod(0.0), 4)
|
|
432
|
+
self.assertEqual(Cached.get_typedclassmethod(0.0), 4)
|
|
433
|
+
self.assertEqual(Cached.get_typedclassmethod(0), 5)
|
|
434
|
+
self.assertEqual(cached.get_typedclassmethod(0), 5)
|
|
@@ -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)
|
|
@@ -76,6 +76,11 @@ class DecoratorTestMixin:
|
|
|
76
76
|
self.assertEqual(cached.cache_info(), (2, 1, 128, 1))
|
|
77
77
|
|
|
78
78
|
def test_decorator_needs_rlock(self):
|
|
79
|
+
"""This will deadlock on a cache that uses a regular lock.
|
|
80
|
+
https://github.com/python/cpython/blob/3.13/Lib/test/test_functools.py#L1791
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
|
|
79
84
|
cached = self.decorator(lambda n: n)
|
|
80
85
|
|
|
81
86
|
class RecursiveEquals:
|
|
@@ -26,6 +26,11 @@ class LFUCacheTest(unittest.TestCase, CacheTestMixin):
|
|
|
26
26
|
self.assertEqual(cache[4], 4)
|
|
27
27
|
self.assertEqual(cache[1], 1)
|
|
28
28
|
|
|
29
|
+
cache[1]
|
|
30
|
+
self.assertEqual(len(cache), 2)
|
|
31
|
+
self.assertEqual(cache[1], 1)
|
|
32
|
+
self.assertEqual(cache[4], 4)
|
|
33
|
+
|
|
29
34
|
def test_lfu_getsizeof(self):
|
|
30
35
|
cache = LFUCache(maxsize=3, getsizeof=lambda x: x)
|
|
31
36
|
|
|
@@ -47,3 +52,15 @@ class LFUCacheTest(unittest.TestCase, CacheTestMixin):
|
|
|
47
52
|
cache[4] = 4
|
|
48
53
|
self.assertEqual(len(cache), 1)
|
|
49
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
|