Merge remote-tracking branch 'main/master' into feat/type-hints-covering

# Conflicts:
#	fastapi_cache/decorator.py
This commit is contained in:
Ivan Moiseev
2022-10-30 10:58:02 +04:00
4 changed files with 20 additions and 8 deletions

View File

@@ -5,6 +5,7 @@
### 0.2.0 ### 0.2.0
- Make `request` and `response` optional. - Make `request` and `response` optional.
- Add typing info to the `cache` decorator.
## 0.1 ## 0.1

View File

@@ -1,6 +1,11 @@
import inspect import inspect
import sys
from functools import wraps from functools import wraps
from typing import Callable, Optional, Type, Any from typing import Any, Awaitable, Callable, Optional, TypeVar
if sys.version_info >= (3, 10):
from typing import ParamSpec
else:
from typing_extensions import ParamSpec
from fastapi.concurrency import run_in_threadpool from fastapi.concurrency import run_in_threadpool
from starlette.requests import Request from starlette.requests import Request
@@ -10,12 +15,16 @@ from fastapi_cache import FastAPICache
from fastapi_cache.coder import Coder from fastapi_cache.coder import Coder
P = ParamSpec("P")
R = TypeVar("R")
def cache( def cache(
expire: Optional[int] = None, expire: Optional[int] = None,
coder: Optional[Type[Coder]] = None, coder: Optional[Coder] = None,
key_builder: Optional[Callable] = None, key_builder: Optional[Callable[..., Any]] = None,
namespace: Optional[str] = "", namespace: Optional[str] = "",
) -> Callable: ) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[R]]]:
""" """
cache all function cache all function
:param namespace: :param namespace:
@@ -26,7 +35,7 @@ def cache(
:return: :return:
""" """
def wrapper(func: Callable) -> Callable: def wrapper(func: Callable[P, Awaitable[R]]) -> Callable[P, Awaitable[R]]:
signature = inspect.signature(func) signature = inspect.signature(func)
request_param = next( request_param = next(
(param for param in signature.parameters.values() if param.annotation is Request), (param for param in signature.parameters.values() if param.annotation is Request),
@@ -55,15 +64,15 @@ def cache(
) )
if parameters: if parameters:
signature = signature.replace(parameters=parameters) signature = signature.replace(parameters=parameters)
func.__signature__ = signature # type: ignore func.__signature__ = signature
@wraps(func) @wraps(func)
async def inner(*args: Any, **kwargs: Any) -> Any: async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
nonlocal coder nonlocal coder
nonlocal expire nonlocal expire
nonlocal key_builder nonlocal key_builder
async def ensure_async_func(*args: Any, **kwargs: Any) -> Any: async def ensure_async_func(*args: P.args, **kwargs: P.kwargs) -> R:
"""Run cached sync functions in thread pool just like FastAPI.""" """Run cached sync functions in thread pool just like FastAPI."""
# if the wrapped function does NOT have request or response in its function signature, # if the wrapped function does NOT have request or response in its function signature,
# make sure we don't pass them in as keyword arguments # make sure we don't pass them in as keyword arguments
@@ -83,6 +92,7 @@ def cache(
# see above why we have to await even although caller also awaits. # see above why we have to await even although caller also awaits.
return await run_in_threadpool(func, *args, **kwargs) return await run_in_threadpool(func, *args, **kwargs)
copy_kwargs = kwargs.copy() copy_kwargs = kwargs.copy()
request = copy_kwargs.pop("request", None) request = copy_kwargs.pop("request", None)
response = copy_kwargs.pop("response", None) response = copy_kwargs.pop("response", None)

0
fastapi_cache/py.typed Normal file
View File

View File

@@ -22,6 +22,7 @@ redis = { version = "^4.2.0rc1", optional = true }
aiomcache = { version = "*", optional = true } aiomcache = { version = "*", optional = true }
pendulum = "*" pendulum = "*"
aiobotocore = { version = "^1.4.1", optional = true } aiobotocore = { version = "^1.4.1", optional = true }
typing-extensions = { version = ">=4.1.0", markers = "python_version < \"3.10\"" }
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
flake8 = "*" flake8 = "*"