Skip to content

Commit 45dad12

Browse files
committed
Adds typing to the decorators
1 parent 63fb637 commit 45dad12

File tree

3 files changed

+188
-4
lines changed

3 files changed

+188
-4
lines changed

aiocache/decorators.pyi

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
from typing import (
2+
Any,
3+
Callable,
4+
Concatenate,
5+
Mapping,
6+
ParamSpec,
7+
Protocol,
8+
Sequence,
9+
Type,
10+
TypeVar,
11+
overload,
12+
)
13+
14+
from aiocache import BaseCache, Cache
15+
from aiocache.plugins import BasePlugin
16+
from aiocache.serializers import BaseSerializer
17+
18+
Params = ParamSpec("Params")
19+
ReturnType = TypeVar("ReturnType")
20+
DecoratorKWArgs = TypeVar("DecoratorKWArgs")
21+
SerializerType = TypeVar("SerializerType", bound=BaseSerializer)
22+
CacheType = TypeVar("CacheType", bound=BaseCache)
23+
MCReturnType = TypeVar("MCReturnType", bound=Mapping)
24+
MCKey = TypeVar("MCKey")
25+
MCVal = TypeVar("MCVal")
26+
27+
class CachedDecorated(Protocol[CacheType, Params, ReturnType]):
28+
cache: CacheType
29+
30+
def __call__(
31+
self,
32+
*args: Params.args,
33+
cache_read: bool = True,
34+
cache_write: bool = True,
35+
aiocache_wait_for_write: bool = True,
36+
**kwargs: Params.kwargs,
37+
) -> ReturnType: ...
38+
39+
class cached:
40+
ttl: int | None
41+
namespace: str | None
42+
serializer: SerializerType | None
43+
plugins: Sequence[BasePlugin] | None
44+
alias: str | None
45+
46+
_cache: CacheType
47+
_serializer: SerializerType
48+
_namespace: str | None
49+
_plugins: Sequence[BasePlugin] | None
50+
_kwargs: dict[str, DecoratorKWArgs]
51+
52+
key_builder: Callable[Params, str] | None
53+
skip_cache_func: Callable[[ReturnType], bool] | None
54+
noself: bool
55+
56+
@overload
57+
def __init__(
58+
self,
59+
ttl: int | None = None,
60+
*,
61+
key_builder: Callable[Params, str] | None = None,
62+
skip_cache_func: Callable[[ReturnType], bool] | None = None,
63+
cache: Type[CacheType] = Cache.MEMORY,
64+
noself: bool = False,
65+
alias: str,
66+
**kwargs: DecoratorKWArgs,
67+
): ...
68+
@overload
69+
def __init__(
70+
self,
71+
ttl: int | None = None,
72+
*,
73+
key_builder: Callable[Params, str] | None = None,
74+
skip_cache_func: Callable[[ReturnType], bool] | None = None,
75+
cache: Type[CacheType] = Cache.MEMORY,
76+
noself: bool = False,
77+
namespace: str | None = None,
78+
serializer: SerializerType | None = None,
79+
plugins: Sequence[BasePlugin] | None = None,
80+
alias: None = None,
81+
**kwargs: DecoratorKWArgs,
82+
): ...
83+
def __call__(
84+
self, fn: Callable[Params, ReturnType]
85+
) -> CachedDecorated[CacheType, Params, ReturnType]: ...
86+
def get_cache_key(self, *args: Params.args, **kwargs: Params.kwargs) -> str: ...
87+
async def get_from_cache(self, key: str) -> ReturnType | None: ...
88+
async def set_in_cache(self, key: str, value: ReturnType) -> None: ...
89+
90+
class cached_stampede(cached):
91+
@overload
92+
def __init__(
93+
self,
94+
lease: int = 2,
95+
ttl: int | None = None,
96+
*,
97+
key_builder: Callable[Params, str] | None = None,
98+
skip_cache_func: Callable[[ReturnType], bool] | None = None,
99+
cache: Type[CacheType] = Cache.MEMORY,
100+
noself: bool = False,
101+
alias: str,
102+
**kwargs: DecoratorKWArgs,
103+
) -> CachedDecorated[CacheType, Params, ReturnType]: ...
104+
@overload
105+
def __init__(
106+
self,
107+
lease: int = 2,
108+
ttl: int | None = None,
109+
*,
110+
key_builder: Callable[Params, str] | None = None,
111+
skip_cache_func: Callable[[ReturnType], bool] | None = None,
112+
cache: Type[CacheType] = Cache.MEMORY,
113+
noself: bool = False,
114+
namespace: str | None = None,
115+
serializer: SerializerType | None = None,
116+
plugins: Sequence[BasePlugin] | None = None,
117+
alias: None = None,
118+
**kwargs: DecoratorKWArgs,
119+
) -> CachedDecorated[CacheType, Params, ReturnType]: ...
120+
121+
class multi_cached:
122+
keys_from_attr: str
123+
key_builder: (
124+
Callable[
125+
Concatenate[
126+
MCKey, CachedDecorated[CacheType, Params, MCReturnType[MCKey, MCVal]], Params
127+
],
128+
str,
129+
]
130+
| None
131+
)
132+
skip_cache_func: Callable[[MCKey, MCVal], bool] | None
133+
134+
@overload
135+
def __init__(
136+
self,
137+
keys_from_attr: str,
138+
*,
139+
key_builder: (
140+
Callable[Concatenate[MCKey, Callable[Params, ReturnType], Params], str] | None
141+
) = None,
142+
skip_cache_func: Callable[[MCKey, MCVal], bool] | None = None,
143+
ttl: int | None = None,
144+
cache: Type[CacheType] = Cache.MEMORY,
145+
alias: str,
146+
**kwargs: DecoratorKWArgs,
147+
): ...
148+
@overload
149+
def __init__(
150+
self,
151+
keys_from_attr: str,
152+
*,
153+
namespace: str | None = None,
154+
key_builder: (
155+
Callable[Concatenate[MCKey, Callable[Params, ReturnType], Params], str] | None
156+
) = None,
157+
skip_cache_func: Callable[[MCKey, MCVal], bool] | None = None,
158+
ttl: int | None = None,
159+
cache: Type[CacheType] = Cache.MEMORY,
160+
serializer: SerializerType | None = None,
161+
plugins: Sequence[BasePlugin] | None = None,
162+
alias: None = None,
163+
**kwargs: DecoratorKWArgs,
164+
): ...
165+
def __call__(
166+
self, fn: Callable[Params, ReturnType]
167+
) -> CachedDecorated[CacheType, Params, MCReturnType]: ...
168+
def get_cache_keys(
169+
self, f: Callable[Params, ReturnType], *args: Params.args, **kwargs: Params.kwargs
170+
) -> str: ...
171+
async def get_from_cache(self, *keys: MCKey) -> list[MCVal | None]: ...
172+
async def set_in_cache(
173+
self,
174+
result: MCReturnType[MCKey, MCVal],
175+
fn: Callable[Params, ReturnType],
176+
fn_args: Params.args,
177+
fn_kwargs: Params.kwargs,
178+
) -> None: ...
179+
180+
def __getattr__(name: str) -> Any: ...

setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ source = aiocache
2525
[coverage:report]
2626
show_missing = true
2727
skip_covered = true
28+
29+
[options.package_data]
30+
{name} = py.typed, *.pyi

tests/ut/test_decorators.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def test_init(self):
6060
def test_fails_at_instantiation(self):
6161
with pytest.raises(TypeError):
6262

63-
@cached(wrong_param=1)
63+
@cached(wrong_param=1) # type: ignore[misc]
6464
async def fn() -> None:
6565
"""Dummy function."""
6666

@@ -373,7 +373,7 @@ def f():
373373
def test_fails_at_instantiation(self):
374374
with pytest.raises(TypeError):
375375

376-
@multi_cached(wrong_param=1)
376+
@multi_cached(wrong_param=1) # type: ignore[misc]
377377
async def fn() -> None:
378378
"""Dummy function."""
379379

@@ -476,8 +476,9 @@ async def test_cache_write_doesnt_wait_for_future(self, mocker, decorator, decor
476476
mocker.spy(decorator, "set_in_cache")
477477
with patch.object(decorator, "get_from_cache", autospec=True, return_value=[None, None]):
478478
with patch("aiocache.decorators.asyncio.ensure_future", autospec=True):
479-
await decorator_call(1, keys=["a", "b"], value="value",
480-
aiocache_wait_for_write=False)
479+
await decorator_call(
480+
1, keys=["a", "b"], value="value", aiocache_wait_for_write=False
481+
)
481482

482483
decorator.set_in_cache.assert_not_awaited()
483484
decorator.set_in_cache.assert_called_once_with({"a": ANY, "b": ANY}, stub_dict, ANY, ANY)

0 commit comments

Comments
 (0)