Skip to content

Commit 68544a6

Browse files
Daniel-Chinpre-commit-ci[bot]Bordashaypal5
authored
Add feature: call with freshness threshold (#262)
* add caller_with_freshness_threshold * fix type * simple test passed * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Jirka Borovec <6035284+Borda@users.noreply.github.com> Co-authored-by: Shay Palachy-Affek <shaypal5@users.noreply.github.com>
1 parent dedb52d commit 68544a6

2 files changed

Lines changed: 43 additions & 4 deletions

File tree

src/cachier/core.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from collections import OrderedDict
1414
from concurrent.futures import ThreadPoolExecutor
1515
from datetime import datetime, timedelta
16-
from functools import wraps
16+
from functools import partial, wraps
1717
from typing import Any, Callable, Optional, Union
1818
from warnings import warn
1919

@@ -225,8 +225,7 @@ def cachier(
225225
def _cachier_decorator(func):
226226
core.set_func(func)
227227

228-
@wraps(func)
229-
def func_wrapper(*args, **kwds):
228+
def _call(*args, max_age: Optional[timedelta] = None, **kwds):
230229
nonlocal allow_none
231230
_allow_none = _update_with_defaults(allow_none, "allow_none", kwds)
232231
# print('Inside general wrapper for {}.'.format(func.__name__))
@@ -271,7 +270,12 @@ def func_wrapper(*args, **kwds):
271270
if _allow_none or entry.value is not None:
272271
_print("Cached result found.")
273272
now = datetime.now()
274-
if now - entry.time <= _stale_after:
273+
stale_delta = (
274+
min(_stale_after, max_age)
275+
if max_age is not None
276+
else _stale_after
277+
)
278+
if now - entry.time <= stale_delta:
275279
_print("And it is fresh!")
276280
return entry.value
277281
_print("But it is stale... :(")
@@ -305,6 +309,8 @@ def func_wrapper(*args, **kwds):
305309
_print("No entry found. No current calc. Calling like a boss.")
306310
return _calc_entry(core, key, func, args, kwds)
307311

312+
func_wrapper = wraps(func)(partial(_call, timedelta.max))
313+
308314
def _clear_cache():
309315
"""Clear the cache."""
310316
core.clear_cache()
@@ -332,10 +338,16 @@ def _precache_value(*args, value_to_cache, **kwds): # noqa: D417
332338
)
333339
return core.precache_value((), kwargs, value_to_cache)
334340

341+
def _caller_with_freshness_threshold(max_age: timedelta):
342+
return wraps(func)(partial(_call, max_age))
343+
335344
func_wrapper.clear_cache = _clear_cache
336345
func_wrapper.clear_being_calculated = _clear_being_calculated
337346
func_wrapper.cache_dpath = _cache_dpath
338347
func_wrapper.precache_value = _precache_value
348+
func_wrapper.caller_with_freshness_threshold = (
349+
_caller_with_freshness_threshold
350+
)
339351
return func_wrapper
340352

341353
return _cachier_decorator
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import time
2+
from datetime import timedelta
3+
4+
import cachier
5+
6+
7+
def test_call_with_freshness_threshold():
8+
@cachier.cachier()
9+
def test_func(a, b):
10+
print("Computing...")
11+
return a + b
12+
13+
print(f"{test_func(1, 2) = }")
14+
print(f"{test_func(1, 2) = }")
15+
caller_with_freshness_threshold = (
16+
test_func.caller_with_freshness_threshold(
17+
timedelta(seconds=0.5),
18+
)
19+
)
20+
print(f"{caller_with_freshness_threshold(1, 2) = }")
21+
print(f"{time.sleep(1.0) = }")
22+
print(f"{test_func(1, 2) = }")
23+
print(f"{caller_with_freshness_threshold(1, 2) = }")
24+
25+
26+
if __name__ == "__main__":
27+
test_call_with_freshness_threshold()

0 commit comments

Comments
 (0)