Skip to content

Commit da961d1

Browse files
committed
refactor: update cache storage initialization to use create_with method
1 parent 7dbb49f commit da961d1

9 files changed

Lines changed: 48 additions & 45 deletions

File tree

README.md

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ pip install cachium
1818
## Quick Start
1919

2020
```python
21+
import asyncio
22+
2123
from cachium import cache
24+
from cachium.storages.ttl_map import TTLMapStorage, TTLMapAsyncStorage
2225

2326
# Simple function caching
24-
@cache()
27+
@cache(storage=TTLMapStorage.create_with(max_size=100, ttl=None))
2528
def expensive_calculation(x: int, y: int) -> int:
26-
print(f"Calculating {x} + {y}")
2729
return x + y
2830

2931
# First call performs the calculation
@@ -35,19 +37,17 @@ result2 = expensive_calculation(1, 2) # No calculation performed
3537
print(result2) # Output: 3
3638

3739
# Async function caching works too
38-
@cache()
39-
async def async_expensive_calculation(x: int, y: int) -> int:
40-
print(f"Calculating {x} + {y} asynchronously")
40+
@cache(storage=TTLMapAsyncStorage.create_with(max_size=100, ttl=None))
41+
async def async_io_operation(x: int, y: int) -> int:
42+
await asyncio.sleep(1) # Simulate an I/O-bound operation
4143
return x + y
4244

43-
# Usage with async functions
44-
import asyncio
4545

4646
async def main():
4747
# First call performs the calculation
48-
result1 = await async_expensive_calculation(1, 2)
48+
result1 = await async_io_operation(1, 2)
4949
# Second call uses cached result
50-
result2 = await async_expensive_calculation(1, 2)
50+
result2 = await async_io_operation(1, 2)
5151

5252
print(result1, result2) # Output: 3 3
5353

@@ -63,28 +63,11 @@ from datetime import timedelta
6363
from cachium import cache
6464
from cachium.storages.ttl_map import TTLMapStorage
6565

66-
@cache(storage=lambda: TTLMapStorage(max_size=100, ttl=timedelta(hours=1)))
66+
@cache(storage=TTLMapStorage.create_with(max_size=100, ttl=timedelta(hours=1)))
6767
def long_lived_cache_function(x):
6868
return x * 2
6969
```
7070

71-
### Custom Key Builders
72-
73-
```python
74-
from cachium import cache, DefaultKeyBuilder
75-
76-
# Create a custom key builder
77-
key_builder = DefaultKeyBuilder(
78-
prefix="custom_prefix",
79-
func=lambda x, y: x + y,
80-
delimiter=":"
81-
)
82-
83-
@cache(key_builder=key_builder)
84-
def my_function(x, y):
85-
return x + y
86-
```
87-
8871
## License
8972

90-
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
73+
See the LICENSE file for details.

cachium/_decorators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def cache(
6262
Minimal usage:
6363
>>> from cachium import cache
6464
>>> from cachium.storages.ttl_map import TTLMapStorage
65-
>>> @cache(storage=lambda: TTLMapStorage())
65+
>>> @cache(storage=TTLMapStorage.create_with())
6666
... def add(a: int, b: int) -> int:
6767
... return a + b
6868
>>> add(1, 2)

cachium/storages/ttl_map.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from asyncio import Condition as AsyncCondition
77
from datetime import timedelta
88
from threading import Condition
9-
from typing import TYPE_CHECKING
9+
from typing import TYPE_CHECKING, Callable
1010

1111
from ttlru_map import TTLMap
1212
from typing_extensions import override
@@ -146,6 +146,16 @@ def __init__(
146146
self._lock_storage = LockStorage()
147147
self._storage: TTLMap[TCacheKey, TValue] = TTLMap(max_size=max_size, ttl=ttl)
148148

149+
@classmethod
150+
def create_with(
151+
cls,
152+
*,
153+
max_size: int | None = 1000,
154+
ttl: timedelta | None = timedelta(minutes=1),
155+
) -> Callable[..., Self]:
156+
"""Return a callable that creates a new instance of `TTLMapAsyncStorage` with the specified parameters."""
157+
return lambda: cls(max_size=max_size, ttl=ttl)
158+
149159
@override
150160
def lock(self, key: TCacheKey, *, timeout: timedelta | None = None) -> SimpleLock:
151161
return SimpleLock(self._lock_storage, key, timeout)
@@ -173,6 +183,16 @@ def __init__(
173183
self._lock_storage = AsyncLockStorage()
174184
self._storage: TTLMap[TCacheKey, TValue] = TTLMap(max_size=max_size, ttl=ttl)
175185

186+
@classmethod
187+
def create_with(
188+
cls,
189+
*,
190+
max_size: int | None = 1000,
191+
ttl: timedelta | None = timedelta(minutes=1),
192+
) -> Callable[..., Self]:
193+
"""Return a callable that creates a new instance of `TTLMapAsyncStorage` with the specified parameters."""
194+
return lambda: cls(max_size=max_size, ttl=ttl)
195+
176196
@override
177197
def lock(self, key: TCacheKey, *, timeout: timedelta | None = None) -> SimpleAsyncLock:
178198
return SimpleAsyncLock(self._lock_storage, key, timeout)

docs/examples.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ from cachium import cache
6363
from cachium.storages.ttl_map import TTLMapStorage
6464
import time
6565

66-
@cache(storage=lambda: TTLMapStorage(ttl=timedelta(seconds=5)))
66+
@cache(storage=TTLMapStorage.create_with(ttl=timedelta(seconds=5)))
6767
def get_timestamp() -> float:
6868
"""Return the current timestamp."""
6969
return time.time()
@@ -92,7 +92,7 @@ print(f"Different timestamp: {ts1 != ts3}") # Output: True
9292
from cachium import cache
9393
from cachium.storages.ttl_map import TTLMapStorage
9494

95-
@cache(storage=lambda: TTLMapStorage(max_size=2)) # Only store the 2 most recently used results
95+
@cache(storage=TTLMapStorage.create_with(max_size=2)) # Only store the 2 most recently used results
9696
def process_data(data_id: int) -> str:
9797
print(f"Processing data {data_id}...")
9898
return f"Processed {data_id}"
@@ -194,7 +194,7 @@ cursor.execute('INSERT INTO users VALUES (1, "Alice")')
194194
cursor.execute('INSERT INTO users VALUES (2, "Bob")')
195195
conn.commit()
196196

197-
@cache(storage=lambda: TTLMapStorage(ttl=timedelta(minutes=5)))
197+
@cache(storage=TTLMapStorage.create_with(ttl=timedelta(minutes=5)))
198198
def get_user(user_id: int) -> dict:
199199
"""Get a user from the database by ID."""
200200
print(f"Fetching user {user_id} from database...")
@@ -226,7 +226,7 @@ from datetime import timedelta
226226
from cachium import cache
227227
from cachium.storages.ttl_map import TTLMapStorage
228228

229-
@cache(storage=lambda: TTLMapStorage(ttl=timedelta(minutes=5)))
229+
@cache(storage=TTLMapStorage.create_with(ttl=timedelta(minutes=5)))
230230
async def fetch_weather(city: str) -> dict:
231231
"""Simulate fetching weather data from an API."""
232232
print(f"Fetching weather data for {city}...")

docs/guides/quickstart.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ from py_cashier import cache
1515
from py_cashier.storages.ttl_map import TTLMapStorage
1616

1717
# Configure TTL and max size
18-
@cache(storage=lambda: TTLMapStorage(max_size=512, ttl=timedelta(seconds=30)))
18+
@cache(storage=TTLMapStorage.create_with(max_size=512, ttl=timedelta(seconds=30)))
1919
def add(a: int, b: int) -> int:
2020
return a + b
2121

@@ -53,7 +53,7 @@ from py_cashier import cache, CacheWith
5353
from py_cashier.storages.ttl_map import TTLMapStorage
5454

5555
# Only `x` participates in the cache key; calls differing only by `y` share the cached result
56-
@cache(storage=lambda: TTLMapStorage())
56+
@cache(storage=TTLMapStorage.create_with())
5757
def compute(x: Annotated[int, CacheWith()], y: int) -> int:
5858
return x + y
5959

docs/guides/tutorials.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ from datetime import timedelta
99
from py_cashier import cache
1010
from py_cashier.storages.ttl_map import TTLMapStorage
1111

12-
@cache(storage=lambda: TTLMapStorage(max_size=1000, ttl=timedelta(minutes=10)))
12+
@cache(storage=TTLMapStorage.create_with(max_size=1000, ttl=timedelta(minutes=10)))
1313
def get_item(key: str) -> str:
1414
return f"value:{key}"
1515
```
@@ -22,7 +22,7 @@ from py_cashier import cache, CacheWith
2222
from py_cashier.storages.ttl_map import TTLMapStorage
2323

2424
# Cache only by `x`, ignore `y` in the cache key
25-
@cache(storage=lambda: TTLMapStorage())
25+
@cache(storage=TTLMapStorage.create_with())
2626
def f_cached(x: Annotated[int, CacheWith()], y: int) -> int:
2727
return x + y
2828
```

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ from datetime import timedelta
2828
from cachium import cache
2929
from cachium.storages.ttl_map import TTLMapStorage
3030

31-
@cache(storage=lambda: TTLMapStorage(max_size=1024, ttl=timedelta(minutes=1)))
31+
@cache(storage=TTLMapStorage.create_with(max_size=1024, ttl=timedelta(minutes=1)))
3232
def add(a: int, b: int) -> int:
3333
return a + b
3434

tests/test__decorator.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_cache(a: int, b: int, expected: int) -> None:
3030
"""Test that the cache decorator works correctly for synchronous functions."""
3131
calls: dict[tuple[int, int], int] = defaultdict(int)
3232

33-
@cache(storage=lambda: TTLMapStorage(max_size=1000, ttl=timedelta(seconds=1)))
33+
@cache(storage=TTLMapStorage.create_with(max_size=1000, ttl=timedelta(seconds=1)))
3434
def func(x: int, y: int) -> int:
3535
nonlocal calls
3636
calls[(x, y)] += 1
@@ -120,7 +120,7 @@ def test_cache_dog_piling_sync(a: int, b: int, expected: int, workers_count: int
120120
"""
121121
calls = 0
122122

123-
@cache(storage=lambda: TTLMapStorage(max_size=1000, ttl=timedelta(seconds=1)))
123+
@cache(storage=TTLMapStorage.create_with(max_size=1000, ttl=timedelta(seconds=1)))
124124
def func(x: int, y: int) -> int:
125125
time.sleep(0.1)
126126
nonlocal calls
@@ -153,7 +153,7 @@ def test_cache_failing_func_sync(a: int, b: int, workers_count: int) -> None:
153153
"""Test that failing functions are not cached in synchronous context."""
154154
calls = 0
155155

156-
@cache(storage=lambda: TTLMapStorage(max_size=1000, ttl=timedelta(seconds=1)))
156+
@cache(storage=TTLMapStorage.create_with(max_size=1000, ttl=timedelta(seconds=1)))
157157
def func(x: int, y: int) -> int:
158158
time.sleep(0.03)
159159
nonlocal calls
@@ -226,7 +226,7 @@ def _f() -> None:
226226
@pytest.mark.parametrize(
227227
("func", "storage"),
228228
[
229-
(_af, lambda: TTLMapStorage(max_size=1000, ttl=timedelta(seconds=1))),
229+
(_af, TTLMapStorage.create_with(max_size=1000, ttl=timedelta(seconds=1))),
230230
(_f, lambda: TTLMapAsyncStorage(max_size=1000, ttl=timedelta(seconds=1))),
231231
],
232232
)
@@ -239,7 +239,7 @@ def test__decorator__invalid_storage(func: Callable[..., Any], storage: PStorage
239239
def test__decorator__cache_only_by_chosen_args():
240240
calls: dict[tuple[str, int, float], int] = defaultdict(int)
241241

242-
@cache(storage=lambda: TTLMapStorage(max_size=1000, ttl=timedelta(seconds=1)))
242+
@cache(storage=TTLMapStorage.create_with(max_size=1000, ttl=timedelta(seconds=1)))
243243
def func(a: Annotated[str, CacheWith()], b: int, c: Annotated[float, CacheWith]) -> str:
244244
nonlocal calls
245245
calls[(a, b, c)] += 1

todo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- 0.1.0 release (choose name for the package)
1+
- Refactor key builder
22
- Redis
33
- Invalidation
44
- get CacheWith annotation from nested decorators

0 commit comments

Comments
 (0)