Skip to content

Commit f5f33e9

Browse files
y-u-n-ii-aYuniia Olkhova
andauthored
feat: Adding extra flag to allow uncached results (#13)
* Add optional use_cache param * Add optional use_cache param * Test optional use_cache param, use black code format Co-authored-by: Yuniia Olkhova <yuniia.olkhova@yalantis.net>
1 parent ebf289b commit f5f33e9

File tree

8 files changed

+64
-22
lines changed

8 files changed

+64
-22
lines changed

README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,7 @@ Advanced Usage
8080
# 2. request object
8181
# 3. any other custom object type.
8282
83+
84+
# If you want to refresh the function result use the `use_cache=False`
85+
# param in the function invocation
86+
func(*args, use_cache=False, **kwargs)

cache/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
from .async_lru import AsyncLRU
2-
from .async_ttl import AsyncTTL
2+
from .async_ttl import AsyncTTL

cache/async_lru.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33

44

55
class AsyncLRU:
6-
76
def __init__(self, maxsize=128):
87
"""
98
:param maxsize: Use maxsize as None for unlimited size cache
109
"""
1110
self.lru = LRU(maxsize=maxsize)
1211

1312
def __call__(self, func):
14-
async def wrapper(*args, **kwargs):
13+
async def wrapper(*args, use_cache=True, **kwargs):
1514
key = KEY(args, kwargs)
16-
if key in self.lru:
15+
if key in self.lru and use_cache:
1716
return self.lru[key]
1817
else:
1918
self.lru[key] = await func(*args, **kwargs)

cache/async_ttl.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
import datetime
2+
13
from .key import KEY
24
from .lru import LRU
3-
import datetime
45

56

67
class AsyncTTL:
78
class _TTL(LRU):
89
def __init__(self, time_to_live, maxsize):
910
super().__init__(maxsize=maxsize)
1011

11-
self.time_to_live = datetime.timedelta(
12-
seconds=time_to_live
13-
) if time_to_live else None
12+
self.time_to_live = (
13+
datetime.timedelta(seconds=time_to_live) if time_to_live else None
14+
)
1415

1516
self.maxsize = maxsize
1617

@@ -31,13 +32,13 @@ def __getitem__(self, key):
3132

3233
def __setitem__(self, key, value):
3334
ttl_value = (
34-
datetime.datetime.now() + self.time_to_live
35-
) if self.time_to_live else None
35+
(datetime.datetime.now() + self.time_to_live)
36+
if self.time_to_live
37+
else None
38+
)
3639
super().__setitem__(key, (value, ttl_value))
3740

38-
def __init__(
39-
self, time_to_live=60, maxsize=1024, skip_args: int = 0
40-
):
41+
def __init__(self, time_to_live=60, maxsize=1024, skip_args: int = 0):
4142
"""
4243
4344
:param time_to_live: Use time_to_live as None for non expiring cache
@@ -48,9 +49,9 @@ def __init__(
4849
self.skip_args = skip_args
4950

5051
def __call__(self, func):
51-
async def wrapper(*args, **kwargs):
52+
async def wrapper(*args, use_cache=True, **kwargs):
5253
key = KEY(args[self.skip_args:], kwargs)
53-
if key in self.ttl:
54+
if key in self.ttl and use_cache:
5455
val = self.ttl[key]
5556
else:
5657
self.ttl[key] = await func(*args, **kwargs)

cache/key.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def _hash(param: Any):
1515
return tuple(map(_hash, param))
1616
if isinstance(param, dict):
1717
return tuple(map(_hash, param.items()))
18-
elif hasattr(param, '__dict__'):
18+
elif hasattr(param, "__dict__"):
1919
return str(vars(param))
2020
else:
2121
return str(param)

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
author_email="iamsinghrajat@gmail.com",
1111
description="An asyncio Cache",
1212
long_description=long_description,
13-
long_description_content_type='text/x-rst',
13+
long_description_content_type="text/x-rst",
1414
url="https://github.com/iamsinghrajat/async-cache",
1515
packages=setuptools.find_packages(),
1616
classifiers=[
1717
"Programming Language :: Python :: 3",
1818
"License :: OSI Approved :: MIT License",
1919
"Operating System :: OS Independent",
2020
],
21-
python_requires='>=3.3',
22-
keywords=['asyncio', 'lru', 'cache', 'async', 'cache', 'lru-cache', 'ttl'],
21+
python_requires=">=3.3",
22+
keywords=["asyncio", "lru", "cache", "async", "cache", "lru-cache", "ttl"],
2323
)

tests/lru_test.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
from cache import AsyncLRU, AsyncTTL
21
import asyncio
32
import time
3+
from timeit import timeit
4+
5+
from cache import AsyncLRU, AsyncTTL
46

57

68
@AsyncLRU(maxsize=128)
@@ -81,8 +83,30 @@ def test_skip_args():
8183
assert t_second_exec < 4000
8284

8385

86+
def test_cache_refreshing_lru():
87+
t1 = timeit(
88+
"asyncio.get_event_loop().run_until_complete(TestClassFunc().obj_func(1))",
89+
globals=globals(),
90+
number=1,
91+
)
92+
t2 = timeit(
93+
"asyncio.get_event_loop().run_until_complete(TestClassFunc().obj_func(1))",
94+
globals=globals(),
95+
number=1,
96+
)
97+
t3 = timeit(
98+
"asyncio.get_event_loop().run_until_complete(TestClassFunc().obj_func(1, use_cache=False))",
99+
globals=globals(),
100+
number=1,
101+
)
102+
103+
assert t1 > t2
104+
assert t1 - t3 <= 0.1
105+
106+
84107
if __name__ == "__main__":
85108
test()
86109
test_obj_fn()
87110
test_class_fn()
88111
test_skip_args()
112+
test_cache_refreshing_lru()

tests/ttl_test.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
from cache import AsyncTTL
21
import asyncio
32
import time
3+
from timeit import timeit
4+
5+
from cache import AsyncTTL
46

57

68
@AsyncTTL(time_to_live=60)
@@ -56,7 +58,19 @@ def cache_expiration_test():
5658
assert t_third_exec > 1000
5759

5860

61+
def test_cache_refreshing_ttl():
62+
t1 = timeit('asyncio.get_event_loop().run_until_complete(short_cleanup_fn(1))',
63+
globals=globals(), number=1)
64+
t2 = timeit('asyncio.get_event_loop().run_until_complete(short_cleanup_fn(1))',
65+
globals=globals(), number=1)
66+
t3 = timeit('asyncio.get_event_loop().run_until_complete(short_cleanup_fn(1, use_cache=False))',
67+
globals=globals(), number=1)
68+
69+
assert t1 > t2
70+
assert t1 - t3 <= 0.1
71+
72+
5973
if __name__ == "__main__":
6074
cache_hit_test()
6175
cache_expiration_test()
62-
76+
test_cache_refreshing_ttl()

0 commit comments

Comments
 (0)