cachetools 7.2.7__tar.gz → 7.2.8__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-7.2.7 → cachetools-7.2.8}/CHANGELOG.rst +9 -0
- {cachetools-7.2.7/src/cachetools.egg-info → cachetools-7.2.8}/PKG-INFO +1 -1
- {cachetools-7.2.7 → cachetools-7.2.8}/docs/index.rst +12 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/__init__.py +1 -1
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/__init__.pyi +7 -9
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/_cachedmethod.py +10 -10
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/keys.py +2 -2
- {cachetools-7.2.7 → cachetools-7.2.8/src/cachetools.egg-info}/PKG-INFO +1 -1
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_keys.py +10 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_threading.py +86 -10
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_tlru.py +20 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_ttl.py +15 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/LICENSE +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/MANIFEST.in +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/README.rst +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/docs/conf.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/pyproject.toml +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/setup.cfg +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/_cached.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/_descriptor.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/func.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/func.pyi +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/keys.pyi +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools/py.typed +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools.egg-info/SOURCES.txt +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools.egg-info/dependency_links.txt +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/src/cachetools.egg-info/top_level.txt +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/__init__.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_cache.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_cached.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_cachedmethod.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_classmethod.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_fifo.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_func.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_lfu.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_lru.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tests/test_rr.py +0 -0
- {cachetools-7.2.7 → cachetools-7.2.8}/tox.ini +0 -0
|
@@ -356,6 +356,16 @@ often called with the same arguments:
|
|
|
356
356
|
implement the `context manager`_ protocol, and will also be used to
|
|
357
357
|
guard access to the cache.
|
|
358
358
|
|
|
359
|
+
.. note::
|
|
360
|
+
|
|
361
|
+
Even though `lock` and `condition` can be passed separately,
|
|
362
|
+
the condition variable must be associated with the lock that
|
|
363
|
+
guards the cache. In practice, when using
|
|
364
|
+
:class:`threading.Lock` and :class:`threading.Condition`, the
|
|
365
|
+
condition variable must be created with the corresponding lock,
|
|
366
|
+
e.g. ``condition=threading.Condition(lock)``; an unrelated
|
|
367
|
+
:class:`threading.Condition` will raise :exc:`RuntimeError`.
|
|
368
|
+
|
|
359
369
|
The decorator's `cache`, `key`, `lock` and `condition` parameters
|
|
360
370
|
are also available as :attr:`cache`, :attr:`cache_key`,
|
|
361
371
|
:attr:`cache_lock` and :attr:`cache_condition` attributes of the
|
|
@@ -548,6 +558,8 @@ often called with the same arguments:
|
|
|
548
558
|
`lock(self)` will only guard access to the cache itself. It is
|
|
549
559
|
the user's responsibility to handle concurrent calls to the
|
|
550
560
|
underlying wrapped method in a multithreaded environment.
|
|
561
|
+
Likewise, a condition variable returned by `condition(self)`
|
|
562
|
+
must be associated with a lock returned by `lock(self)`.
|
|
551
563
|
|
|
552
564
|
Similarly to the :func:`cached` function decorator, the `cache`,
|
|
553
565
|
`key`, `lock` and `condition` parameters are also available as
|
|
@@ -36,8 +36,6 @@ _T = TypeVar("_T")
|
|
|
36
36
|
_KT = TypeVar("_KT")
|
|
37
37
|
_VT = TypeVar("_VT")
|
|
38
38
|
_TT = TypeVar("_TT", default=float)
|
|
39
|
-
_KT2 = TypeVar("_KT2")
|
|
40
|
-
_VT2 = TypeVar("_VT2")
|
|
41
39
|
|
|
42
40
|
class Cache(MutableMapping[_KT, _VT]):
|
|
43
41
|
def __init__(
|
|
@@ -94,13 +92,13 @@ class _TimedCache(Cache[_KT, _VT], Generic[_KT, _VT, _TT]):
|
|
|
94
92
|
def timer(self) -> _Timer[_TT]: ...
|
|
95
93
|
|
|
96
94
|
class TTLCache(_TimedCache[_KT, _VT, _TT]):
|
|
97
|
-
@overload
|
|
95
|
+
@overload # without timer, _TT takes its default
|
|
98
96
|
def __init__(
|
|
99
|
-
self
|
|
97
|
+
self,
|
|
100
98
|
maxsize: float,
|
|
101
99
|
ttl: float,
|
|
102
100
|
*,
|
|
103
|
-
getsizeof: Callable[[
|
|
101
|
+
getsizeof: Callable[[_VT], float] | None = None,
|
|
104
102
|
) -> None: ...
|
|
105
103
|
@overload
|
|
106
104
|
def __init__(
|
|
@@ -115,13 +113,13 @@ class TTLCache(_TimedCache[_KT, _VT, _TT]):
|
|
|
115
113
|
def expire(self, time: _TT | None = None) -> list[tuple[_KT, _VT]]: ...
|
|
116
114
|
|
|
117
115
|
class TLRUCache(_TimedCache[_KT, _VT, _TT]):
|
|
118
|
-
@overload
|
|
116
|
+
@overload # without timer, _TT takes its default
|
|
119
117
|
def __init__(
|
|
120
|
-
self
|
|
118
|
+
self,
|
|
121
119
|
maxsize: float,
|
|
122
|
-
ttu: Callable[[
|
|
120
|
+
ttu: Callable[[_KT, _VT, float], float],
|
|
123
121
|
*,
|
|
124
|
-
getsizeof: Callable[[
|
|
122
|
+
getsizeof: Callable[[_VT], float] | None = None,
|
|
125
123
|
) -> None: ...
|
|
126
124
|
@overload
|
|
127
125
|
def __init__(
|
|
@@ -35,7 +35,7 @@ class _WrapperBase:
|
|
|
35
35
|
# wrappers
|
|
36
36
|
return (self.__descriptor.__get__, (self._obj,))
|
|
37
37
|
|
|
38
|
-
def __call__(self, *args, **kwargs):
|
|
38
|
+
def __call__(self, /, *args, **kwargs):
|
|
39
39
|
raise NotImplementedError() # pragma: no cover
|
|
40
40
|
|
|
41
41
|
def cache_clear(self):
|
|
@@ -72,7 +72,7 @@ def _condition_info(method, cache, key, lock, cond, info):
|
|
|
72
72
|
self.__hits = self.__misses = 0
|
|
73
73
|
self.__pending = set()
|
|
74
74
|
|
|
75
|
-
def __call__(self, *args, **kwargs):
|
|
75
|
+
def __call__(self, /, *args, **kwargs):
|
|
76
76
|
cache = self.cache
|
|
77
77
|
lock = self.cache_lock
|
|
78
78
|
cond = self.cache_condition
|
|
@@ -121,7 +121,7 @@ def _locked_info(method, cache, key, lock, info):
|
|
|
121
121
|
super().__init__(obj, descriptor, method, cache, key, lock)
|
|
122
122
|
self.__hits = self.__misses = 0
|
|
123
123
|
|
|
124
|
-
def __call__(self, *args, **kwargs):
|
|
124
|
+
def __call__(self, /, *args, **kwargs):
|
|
125
125
|
cache = self.cache
|
|
126
126
|
lock = self.cache_lock
|
|
127
127
|
key = self.cache_key(*args, **kwargs)
|
|
@@ -161,7 +161,7 @@ def _unlocked_info(method, cache, key, info):
|
|
|
161
161
|
super().__init__(obj, descriptor, method, cache, key)
|
|
162
162
|
self.__hits = self.__misses = 0
|
|
163
163
|
|
|
164
|
-
def __call__(self, *args, **kwargs):
|
|
164
|
+
def __call__(self, /, *args, **kwargs):
|
|
165
165
|
cache = self.cache
|
|
166
166
|
key = self.cache_key(*args, **kwargs)
|
|
167
167
|
try:
|
|
@@ -220,7 +220,7 @@ def _condition(method, cache, key, lock, cond):
|
|
|
220
220
|
with lock(self):
|
|
221
221
|
c.clear()
|
|
222
222
|
|
|
223
|
-
def classmethod_wrapper(self, *args, **kwargs):
|
|
223
|
+
def classmethod_wrapper(self, /, *args, **kwargs):
|
|
224
224
|
p = pending.setdefault(self, set())
|
|
225
225
|
return wrapper(self, p, *args, **kwargs)
|
|
226
226
|
|
|
@@ -230,7 +230,7 @@ def _condition(method, cache, key, lock, cond):
|
|
|
230
230
|
super().__init__(obj, descriptor, method, cache, key, lock, cond)
|
|
231
231
|
self.__pending = set()
|
|
232
232
|
|
|
233
|
-
def __call__(self, *args, **kwargs):
|
|
233
|
+
def __call__(self, /, *args, **kwargs):
|
|
234
234
|
return wrapper(self._obj, self.__pending, *args, **kwargs)
|
|
235
235
|
|
|
236
236
|
# objtype: backward-compatible @classmethod handling with Python < 3.13
|
|
@@ -241,7 +241,7 @@ def _condition(method, cache, key, lock, cond):
|
|
|
241
241
|
|
|
242
242
|
|
|
243
243
|
def _locked(method, cache, key, lock):
|
|
244
|
-
def wrapper(self, *args, **kwargs):
|
|
244
|
+
def wrapper(self, /, *args, **kwargs):
|
|
245
245
|
c = cache(self)
|
|
246
246
|
k = key(self, *args, **kwargs)
|
|
247
247
|
with lock(self):
|
|
@@ -269,7 +269,7 @@ def _locked(method, cache, key, lock):
|
|
|
269
269
|
def __init__(self, obj, descriptor):
|
|
270
270
|
super().__init__(obj, descriptor, method, cache, key, lock)
|
|
271
271
|
|
|
272
|
-
def __call__(self, *args, **kwargs):
|
|
272
|
+
def __call__(self, /, *args, **kwargs):
|
|
273
273
|
return wrapper(self._obj, *args, **kwargs)
|
|
274
274
|
|
|
275
275
|
# objtype: backward-compatible @classmethod handling with Python < 3.13
|
|
@@ -280,7 +280,7 @@ def _locked(method, cache, key, lock):
|
|
|
280
280
|
|
|
281
281
|
|
|
282
282
|
def _unlocked(method, cache, key):
|
|
283
|
-
def wrapper(self, *args, **kwargs):
|
|
283
|
+
def wrapper(self, /, *args, **kwargs):
|
|
284
284
|
c = cache(self)
|
|
285
285
|
k = key(self, *args, **kwargs)
|
|
286
286
|
try:
|
|
@@ -303,7 +303,7 @@ def _unlocked(method, cache, key):
|
|
|
303
303
|
def __init__(self, obj, descriptor):
|
|
304
304
|
super().__init__(obj, descriptor, method, cache, key)
|
|
305
305
|
|
|
306
|
-
def __call__(self, *args, **kwargs):
|
|
306
|
+
def __call__(self, /, *args, **kwargs):
|
|
307
307
|
return wrapper(self._obj, *args, **kwargs)
|
|
308
308
|
|
|
309
309
|
# objtype: backward-compatible @classmethod handling with Python < 3.13
|
|
@@ -54,7 +54,7 @@ def hashkey(*args, **kwargs):
|
|
|
54
54
|
return _HashedTuple(args)
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
def methodkey(self, *args, **kwargs):
|
|
57
|
+
def methodkey(self, /, *args, **kwargs):
|
|
58
58
|
"""Return a cache key for use with cached methods."""
|
|
59
59
|
return hashkey(*args, **kwargs)
|
|
60
60
|
|
|
@@ -72,6 +72,6 @@ def typedkey(*args, **kwargs):
|
|
|
72
72
|
return key
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
def typedmethodkey(self, *args, **kwargs):
|
|
75
|
+
def typedmethodkey(self, /, *args, **kwargs):
|
|
76
76
|
"""Return a typed cache key for use with cached methods."""
|
|
77
77
|
return typedkey(*args, **kwargs)
|
|
@@ -38,6 +38,9 @@ class CacheKeysTest(unittest.TestCase):
|
|
|
38
38
|
# untyped keys compare equal
|
|
39
39
|
self.assertEqual(key("x", 1, 2, 3), key("y", 1.0, 2.0, 3.0))
|
|
40
40
|
self.assertEqual(hash(key("x", 1, 2, 3)), hash(key("y", 1.0, 2.0, 3.0)))
|
|
41
|
+
# "self" is positional-only, so it may also be a keyword argument
|
|
42
|
+
self.assertEqual(key("x", self=1), key("y", self=1))
|
|
43
|
+
self.assertNotEqual(key("x", self=1), key("x"))
|
|
41
44
|
|
|
42
45
|
def test_typedkey(self, key=cachetools.keys.typedkey):
|
|
43
46
|
self.assertEqual(key(), key())
|
|
@@ -54,6 +57,8 @@ class CacheKeysTest(unittest.TestCase):
|
|
|
54
57
|
hash(key({}))
|
|
55
58
|
# typed keys compare unequal
|
|
56
59
|
self.assertNotEqual(key(1, 2, 3), key(1.0, 2.0, 3.0))
|
|
60
|
+
self.assertNotEqual(key(1, 2, 3, x=0), key(1, 2, 3, x=0.0))
|
|
61
|
+
self.assertNotEqual(key(1, 2, 3, x=0), key(1, 2, 3, x=False))
|
|
57
62
|
|
|
58
63
|
def test_typedmethodkey(self, key=cachetools.keys.typedmethodkey):
|
|
59
64
|
# similar to typedkey(), but ignores its first positional argument
|
|
@@ -71,6 +76,11 @@ class CacheKeysTest(unittest.TestCase):
|
|
|
71
76
|
hash(key("x", {}))
|
|
72
77
|
# typed keys compare unequal
|
|
73
78
|
self.assertNotEqual(key("x", 1, 2, 3), key("x", 1.0, 2.0, 3.0))
|
|
79
|
+
self.assertNotEqual(key("x", 1, 2, 3, x=0), key("x", 1, 2, 3, x=0.0))
|
|
80
|
+
self.assertNotEqual(key("x", 1, 2, 3, x=0), key("x", 1, 2, 3, x=False))
|
|
81
|
+
# "self" is positional-only, so it may also be a keyword argument
|
|
82
|
+
self.assertEqual(key("x", self=1), key("y", self=1))
|
|
83
|
+
self.assertNotEqual(key("x", self=1), key("x", self=1.0))
|
|
74
84
|
|
|
75
85
|
def test_addkeys(self, key=cachetools.keys.hashkey):
|
|
76
86
|
self.assertIsInstance(key(), tuple)
|
|
@@ -5,8 +5,8 @@ from cachetools import LRUCache, cached, cachedmethod
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class WaitCondition(Condition):
|
|
8
|
-
def __init__(self):
|
|
9
|
-
super().__init__()
|
|
8
|
+
def __init__(self, lock=None):
|
|
9
|
+
super().__init__(lock)
|
|
10
10
|
self.waiting = Event()
|
|
11
11
|
|
|
12
12
|
def wait(self, timeout=None):
|
|
@@ -93,6 +93,90 @@ class ThreadingTest(unittest.TestCase):
|
|
|
93
93
|
func = Cached().method
|
|
94
94
|
self.run_cond_wait_test(func, cond, started, release, calls)
|
|
95
95
|
|
|
96
|
+
def test_cached_lock_cond(self):
|
|
97
|
+
for info in (False, True):
|
|
98
|
+
with self.subTest(info=info):
|
|
99
|
+
cache = LRUCache(1)
|
|
100
|
+
lock = Lock()
|
|
101
|
+
cond = WaitCondition(lock)
|
|
102
|
+
started = Event()
|
|
103
|
+
release = Event()
|
|
104
|
+
calls = []
|
|
105
|
+
|
|
106
|
+
@cached(cache, lock=lock, condition=cond, info=info)
|
|
107
|
+
def func(calls=calls, started=started, release=release):
|
|
108
|
+
calls.append(None)
|
|
109
|
+
started.set()
|
|
110
|
+
release.wait(self.TIMEOUT)
|
|
111
|
+
return object()
|
|
112
|
+
|
|
113
|
+
self.run_cond_wait_test(func, cond, started, release, calls)
|
|
114
|
+
|
|
115
|
+
def test_cachedmethod_lock_cond(self):
|
|
116
|
+
for info in (False, True):
|
|
117
|
+
with self.subTest(info=info):
|
|
118
|
+
cache = LRUCache(1)
|
|
119
|
+
lock = Lock()
|
|
120
|
+
cond = WaitCondition(lock)
|
|
121
|
+
started = Event()
|
|
122
|
+
release = Event()
|
|
123
|
+
calls = []
|
|
124
|
+
|
|
125
|
+
class Cached:
|
|
126
|
+
@cachedmethod(
|
|
127
|
+
lambda _: cache,
|
|
128
|
+
lock=lambda _: lock,
|
|
129
|
+
condition=lambda _: cond,
|
|
130
|
+
info=info,
|
|
131
|
+
)
|
|
132
|
+
def method(
|
|
133
|
+
self,
|
|
134
|
+
calls=calls,
|
|
135
|
+
started=started,
|
|
136
|
+
release=release,
|
|
137
|
+
timeout=self.TIMEOUT,
|
|
138
|
+
):
|
|
139
|
+
calls.append(None)
|
|
140
|
+
started.set()
|
|
141
|
+
release.wait(timeout)
|
|
142
|
+
return object()
|
|
143
|
+
|
|
144
|
+
func = Cached().method
|
|
145
|
+
self.run_cond_wait_test(func, cond, started, release, calls)
|
|
146
|
+
|
|
147
|
+
def test_cached_unrelated_lock_cond(self):
|
|
148
|
+
# a condition variable not created with the lock fails on
|
|
149
|
+
# the first cache miss, even without concurrent calls
|
|
150
|
+
for info in (False, True):
|
|
151
|
+
with self.subTest(info=info):
|
|
152
|
+
|
|
153
|
+
@cached(LRUCache(1), lock=Lock(), condition=Condition(), info=info)
|
|
154
|
+
def func():
|
|
155
|
+
return object()
|
|
156
|
+
|
|
157
|
+
with self.assertRaises(RuntimeError):
|
|
158
|
+
func()
|
|
159
|
+
|
|
160
|
+
def test_cachedmethod_unrelated_lock_cond(self):
|
|
161
|
+
for info in (False, True):
|
|
162
|
+
with self.subTest(info=info):
|
|
163
|
+
cache = LRUCache(1)
|
|
164
|
+
lock = Lock()
|
|
165
|
+
cond = Condition()
|
|
166
|
+
|
|
167
|
+
class Cached:
|
|
168
|
+
@cachedmethod(
|
|
169
|
+
lambda _: cache,
|
|
170
|
+
lock=lambda _: lock,
|
|
171
|
+
condition=lambda _: cond,
|
|
172
|
+
info=info,
|
|
173
|
+
)
|
|
174
|
+
def method(self):
|
|
175
|
+
return object()
|
|
176
|
+
|
|
177
|
+
with self.assertRaises(RuntimeError):
|
|
178
|
+
Cached().method()
|
|
179
|
+
|
|
96
180
|
def run_cond_wait_test(self, func, cond, started, release, calls):
|
|
97
181
|
results = [None] * 2
|
|
98
182
|
|
|
@@ -122,14 +206,6 @@ class ThreadingTest(unittest.TestCase):
|
|
|
122
206
|
self.assertEqual(cache_info.hits + cache_info.misses, self.NTHREADS)
|
|
123
207
|
self.assertGreaterEqual(cache_info.misses, 1)
|
|
124
208
|
|
|
125
|
-
def run_cond_test(self, func, cache, info):
|
|
126
|
-
self.run_threading_test(func, cache)
|
|
127
|
-
|
|
128
|
-
if info:
|
|
129
|
-
cache_info = func.cache_info()
|
|
130
|
-
self.assertEqual(cache_info.hits, self.NTHREADS - 1)
|
|
131
|
-
self.assertEqual(cache_info.misses, 1)
|
|
132
|
-
|
|
133
209
|
def run_threading_test(self, func, cache):
|
|
134
210
|
results = [None] * self.NTHREADS
|
|
135
211
|
|
|
@@ -400,3 +400,23 @@ class TLRUCacheTest(unittest.TestCase, CacheTestMixin):
|
|
|
400
400
|
cache.timer.tick()
|
|
401
401
|
cache.timer.tick() # past TTL
|
|
402
402
|
self.assertNotIn(42, cache)
|
|
403
|
+
|
|
404
|
+
def test_tlru_default_timer_stubs(self):
|
|
405
|
+
# type stubs must infer key and value types with the default timer
|
|
406
|
+
def ttu(_key: str, value: int, now: float) -> float:
|
|
407
|
+
return now + value
|
|
408
|
+
|
|
409
|
+
cache: TLRUCache[str, int] = TLRUCache(maxsize=2, ttu=ttu)
|
|
410
|
+
|
|
411
|
+
cache["a"] = 3600
|
|
412
|
+
self.assertEqual(3600, cache["a"])
|
|
413
|
+
self.assertEqual(1, len(cache))
|
|
414
|
+
self.assertIn("a", cache)
|
|
415
|
+
|
|
416
|
+
sized: TLRUCache[str, str] = TLRUCache(
|
|
417
|
+
maxsize=10, ttu=lambda _k, _v, now: now + 3600, getsizeof=len
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
sized["abc"] = "abc"
|
|
421
|
+
self.assertEqual("abc", sized["abc"])
|
|
422
|
+
self.assertEqual(3, sized.currsize)
|
|
@@ -272,3 +272,18 @@ class TTLCacheTest(unittest.TestCase, CacheTestMixin):
|
|
|
272
272
|
cache.timer.tick()
|
|
273
273
|
cache.timer.tick() # past TTL
|
|
274
274
|
self.assertNotIn(42, cache)
|
|
275
|
+
|
|
276
|
+
def test_ttl_default_timer_stubs(self):
|
|
277
|
+
# type stubs must infer key and value types with the default timer
|
|
278
|
+
cache: TTLCache[str, int] = TTLCache(maxsize=2, ttl=math.inf)
|
|
279
|
+
|
|
280
|
+
cache["a"] = 1
|
|
281
|
+
self.assertEqual(1, cache["a"])
|
|
282
|
+
self.assertEqual(1, len(cache))
|
|
283
|
+
self.assertIn("a", cache)
|
|
284
|
+
|
|
285
|
+
sized: TTLCache[str, str] = TTLCache(maxsize=10, ttl=math.inf, getsizeof=len)
|
|
286
|
+
|
|
287
|
+
sized["abc"] = "abc"
|
|
288
|
+
self.assertEqual("abc", sized["abc"])
|
|
289
|
+
self.assertEqual(3, sized.currsize)
|
|
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
|
|
File without changes
|
|
File without changes
|