@@ -39,6 +39,10 @@ class cached:
39
39
:param key_builder: Callable that allows to build the function dynamically. It receives
40
40
the function plus same args and kwargs passed to the function.
41
41
This behavior is necessarily different than ``BaseCache.build_key()``
42
+ :param skip_cache_func: Callable that receives the result after calling the
43
+ wrapped function and should return `True` if the value should skip the
44
+ cache (or `False` to store in the cache).
45
+ e.g. to avoid caching `None` results: `lambda r: r is None`
42
46
:param cache: cache class to use when calling the ``set``/``get`` operations.
43
47
Default is :class:`aiocache.SimpleMemoryCache`.
44
48
:param serializer: serializer instance to use when calling the ``dumps``/``loads``.
@@ -58,6 +62,7 @@ def __init__(
58
62
ttl = SENTINEL ,
59
63
namespace = None ,
60
64
key_builder = None ,
65
+ skip_cache_func = lambda x : False ,
61
66
cache = Cache .MEMORY ,
62
67
serializer = None ,
63
68
plugins = None ,
@@ -67,6 +72,7 @@ def __init__(
67
72
):
68
73
self .ttl = ttl
69
74
self .key_builder = key_builder
75
+ self .skip_cache_func = skip_cache_func
70
76
self .noself = noself
71
77
self .alias = alias
72
78
self .cache = None
@@ -111,6 +117,9 @@ async def decorator(
111
117
112
118
result = await f (* args , ** kwargs )
113
119
120
+ if self .skip_cache_func (result ):
121
+ return result
122
+
114
123
if cache_write :
115
124
if aiocache_wait_for_write :
116
125
await self .set_in_cache (key , result )
@@ -171,6 +180,10 @@ class cached_stampede(cached):
171
180
:param key_builder: Callable that allows to build the function dynamically. It receives
172
181
the function plus same args and kwargs passed to the function.
173
182
This behavior is necessarily different than ``BaseCache.build_key()``
183
+ :param skip_cache_func: Callable that receives the result after calling the
184
+ wrapped function and should return `True` if the value should skip the
185
+ cache (or `False` to store in the cache).
186
+ e.g. to avoid caching `None` results: `lambda r: r is None`
174
187
:param cache: cache class to use when calling the ``set``/``get`` operations.
175
188
Default is :class:`aiocache.SimpleMemoryCache`.
176
189
:param serializer: serializer instance to use when calling the ``dumps``/``loads``.
@@ -202,6 +215,9 @@ async def decorator(self, f, *args, **kwargs):
202
215
203
216
result = await f (* args , ** kwargs )
204
217
218
+ if self .skip_cache_func (result ):
219
+ return result
220
+
205
221
await self .set_in_cache (key , result )
206
222
207
223
return result
@@ -268,6 +284,9 @@ class multi_cached:
268
284
``keys_from_attr``, the decorated callable, and the positional and keyword arguments
269
285
that were passed to the decorated callable. This behavior is necessarily different than
270
286
``BaseCache.build_key()`` and the call signature differs from ``cached.key_builder``.
287
+ :param skip_cache_keys: Callable that receives both key and value and returns True
288
+ if that key-value pair should not be cached (or False to store in cache).
289
+ The keys and values to be passed are taken from the wrapped function result.
271
290
:param ttl: int seconds to store the keys. Default is 0 which means no expiration.
272
291
:param cache: cache class to use when calling the ``multi_set``/``multi_get`` operations.
273
292
Default is :class:`aiocache.SimpleMemoryCache`.
@@ -286,6 +305,7 @@ def __init__(
286
305
keys_from_attr ,
287
306
namespace = None ,
288
307
key_builder = None ,
308
+ skip_cache_func = lambda k , v : False ,
289
309
ttl = SENTINEL ,
290
310
cache = Cache .MEMORY ,
291
311
serializer = None ,
@@ -295,6 +315,7 @@ def __init__(
295
315
):
296
316
self .keys_from_attr = keys_from_attr
297
317
self .key_builder = key_builder or (lambda key , f , * args , ** kwargs : key )
318
+ self .skip_cache_func = skip_cache_func
298
319
self .ttl = ttl
299
320
self .alias = alias
300
321
self .cache = None
@@ -354,12 +375,17 @@ async def decorator(
354
375
result = await f (* new_args , ** kwargs )
355
376
result .update (partial )
356
377
378
+ to_cache = {k : v for k , v in result .items () if not self .skip_cache_func (k , v )}
379
+
380
+ if not to_cache :
381
+ return result
382
+
357
383
if cache_write :
358
384
if aiocache_wait_for_write :
359
- await self .set_in_cache (result , f , args , kwargs )
385
+ await self .set_in_cache (to_cache , f , args , kwargs )
360
386
else :
361
387
# TODO: Use aiojobs to avoid warnings.
362
- asyncio .create_task (self .set_in_cache (result , f , args , kwargs ))
388
+ asyncio .create_task (self .set_in_cache (to_cache , f , args , kwargs ))
363
389
364
390
return result
365
391
0 commit comments