Merge branch 'long2ice:main' into fix/piclke-coder

This commit is contained in:
Ivan Moiseev
2023-01-11 16:26:05 +03:00
committed by GitHub
7 changed files with 51 additions and 14 deletions

View File

@@ -2,14 +2,16 @@
## 0.2
### 0.2.1
- Support cache jinja2 template response.
### 0.2.0
- Make `request` and `response` optional.
- Add typing info to the `cache` decorator.
- Support cache jinja2 template response.
- Support cache `JSONResponse`
- Add `py.typed` file and type hints
- Add TestCase
- Fix cache decorate sync function
- Transparently handle backend connection failures.
## 0.1

View File

@@ -2,7 +2,7 @@ import pendulum
import uvicorn
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import Response
from starlette.responses import JSONResponse, Response
from fastapi_cache import FastAPICache
from fastapi_cache.backends.inmemory import InMemoryBackend
@@ -51,6 +51,12 @@ def sync_me():
return 42
@app.get("/cache_response_obj")
@cache(namespace="test", expire=5)
async def cache_response_obj():
return JSONResponse({"a": 1})
@app.on_event("startup")
async def startup():
FastAPICache.init(InMemoryBackend())

View File

@@ -9,7 +9,7 @@ from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from redis.asyncio.connection import ConnectionPool
from starlette.requests import Request
from starlette.responses import Response
from starlette.responses import JSONResponse, Response
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
@@ -73,6 +73,12 @@ async def cache_html(request: Request):
return templates.TemplateResponse("index.html", {"request": request, "ret": await get_ret()})
@app.get("/cache_response_obj")
@cache(namespace="test", expire=5)
async def cache_response_obj():
return JSONResponse({"a": 1})
@app.on_event("startup")
async def startup():
pool = ConnectionPool.from_url(url="redis://redis")

View File

@@ -7,6 +7,7 @@ from typing import Any
import pendulum
from fastapi.encoders import jsonable_encoder
from starlette.responses import JSONResponse
from starlette.templating import _TemplateResponse as TemplateResponse
CONVERTERS = {
@@ -52,6 +53,8 @@ class Coder:
class JsonCoder(Coder):
@classmethod
def encode(cls, value: Any) -> str:
if isinstance(value, JSONResponse):
return value.body
return json.dumps(value, cls=JsonEncoder)
@classmethod

View File

@@ -77,9 +77,9 @@ def cache(
# 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
if not request_param:
kwargs.pop("request")
kwargs.pop("request", None)
if not response_param:
kwargs.pop("response")
kwargs.pop("response", None)
if inspect.iscoroutinefunction(func):
# async, return as is.
@@ -123,13 +123,20 @@ def cache(
args=args,
kwargs=copy_kwargs,
)
ttl, ret = await backend.get_with_ttl(cache_key)
try:
ttl, ret = await backend.get_with_ttl(cache_key)
except ConnectionError:
ttl, ret = 0, None
if not request:
if ret is not None:
return coder.decode(ret)
ret = await ensure_async_func(*args, **kwargs)
await backend.set(cache_key, coder.encode(ret), expire or FastAPICache.get_expire())
try:
await backend.set(
cache_key, coder.encode(ret), expire or FastAPICache.get_expire()
)
except ConnectionError:
pass
return ret
if request.method != "GET":
@@ -148,7 +155,10 @@ def cache(
ret = await ensure_async_func(*args, **kwargs)
await backend.set(cache_key, coder.encode(ret), expire or FastAPICache.get_expire())
try:
await backend.set(cache_key, coder.encode(ret), expire or FastAPICache.get_expire())
except ConnectionError:
pass
return ret
return inner

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "fastapi-cache2"
version = "0.2.1"
version = "0.2.0"
description = "Cache for FastAPI"
authors = ["long2ice <long2ice@gmail.com>"]
license = "Apache-2.0"
@@ -23,7 +23,7 @@ aiomcache = { version = "*", optional = true }
pendulum = "*"
aiobotocore = { version = "^1.4.1", optional = true }
typing-extensions = { version = ">=4.1.0", markers = "python_version < \"3.10\"" }
aiohttp= { version = ">=3.8.3", markers = "python_version >= \"3.11\""}
aiohttp = { version = ">=3.8.3", markers = "python_version >= \"3.11\"" }
[tool.poetry.dev-dependencies]
flake8 = "*"

View File

@@ -57,3 +57,13 @@ def test_sync() -> None:
with TestClient(app) as client:
response = client.get("/sync-me")
assert response.json() == 42
def test_cache_response_obj() -> None:
with TestClient(app) as client:
cache_response = client.get("cache_response_obj")
assert cache_response.json() == {"a": 1}
get_cache_response = client.get("cache_response_obj")
assert get_cache_response.json() == {"a": 1}
assert get_cache_response.headers.get("cache-control")
assert get_cache_response.headers.get("etag")