This commit is contained in:
long2ice
2024-07-24 22:24:30 +08:00
parent 701d83fec3
commit 5f985a8506
8 changed files with 2279 additions and 1520 deletions

View File

@@ -12,6 +12,7 @@ from pydantic import BaseModel
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
@asynccontextmanager
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
FastAPICache.init(InMemoryBackend())
@@ -64,7 +65,7 @@ async def get_kwargs(name: str):
@app.get("/sync-me")
@cache(namespace="test")
@cache(namespace="test") # pyright: ignore[reportArgumentType]
def sync_me():
# as per the fastapi docs, this sync function is wrapped in a thread,
# thereby converted to async. fastapi-cache does the same.
@@ -125,7 +126,7 @@ async def cached_put():
@app.get("/namespaced_injection")
@cache(namespace="test", expire=5, injected_dependency_namespace="monty_python")
@cache(namespace="test", expire=5, injected_dependency_namespace="monty_python") # pyright: ignore[reportArgumentType]
def namespaced_injection(
__fastapi_cache_request: int = 42, __fastapi_cache_response: int = 17
) -> Dict[str, int]:

View File

@@ -1,6 +1,6 @@
# pyright: reportGeneralTypeIssues=false
from contextlib import asynccontextmanager
import time
from contextlib import asynccontextmanager
from typing import AsyncIterator
import pendulum
@@ -19,6 +19,7 @@ from starlette.responses import JSONResponse, Response
import redis.asyncio as redis
from redis.asyncio.connection import ConnectionPool
@asynccontextmanager
async def lifespan(_: FastAPI) -> AsyncIterator[None]:
pool = ConnectionPool.from_url(url="redis://redis")
@@ -65,7 +66,7 @@ async def get_data(request: Request, response: Response):
# Note: This function MUST be sync to demonstrate fastapi-cache's correct handling,
# i.e. running cached sync functions in threadpool just like FastAPI itself!
@app.get("/blocking")
@cache(namespace="test", expire=10)
@cache(namespace="test", expire=10) # pyright: ignore[reportArgumentType]
def blocking():
time.sleep(2)
return {"ret": 42}

View File

@@ -1,14 +1,6 @@
from importlib.metadata import version
from typing import ClassVar, Optional, Type
# Because this project supports python 3.7 and up, Pyright treats importlib as
# an external library and so needs to be told to ignore the type issues it sees.
try:
# Python 3.8+
from importlib.metadata import version # type: ignore
except ImportError:
# Python 3.7
from importlib_metadata import version # type: ignore
from fastapi_cache.coder import Coder, JsonCoder
from fastapi_cache.key_builder import default_key_builder
from fastapi_cache.types import Backend, KeyBuilder

View File

@@ -29,8 +29,8 @@ _T = TypeVar("_T", bound=type)
CONVERTERS: Dict[str, Callable[[str], Any]] = {
# Pendulum 3.0.0 adds parse to __all__, at which point these ignores can be removed
"date": lambda x: pendulum.parse(x, exact=True), # type: ignore[attr-defined]
"datetime": lambda x: pendulum.parse(x, exact=True), # type: ignore[attr-defined]
"date": lambda x: pendulum.parse(x, exact=True),
"datetime": lambda x: pendulum.parse(x, exact=True),
"decimal": Decimal,
}

View File

@@ -93,6 +93,7 @@ def cache(
) -> Callable[[Callable[P, Awaitable[R]]], Callable[P, Awaitable[Union[R, Response]]]]:
"""
cache all function
:param injected_dependency_namespace:
:param namespace:
:param expire:
:param coder:

3722
poetry.lock generated

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "fastapi-cache2"
version = "0.2.1"
version = "0.2.2"
description = "Cache for FastAPI"
authors = ["long2ice <long2ice@gmail.com>"]
license = "Apache-2.0"
@@ -15,22 +15,22 @@ packages = [
include = ["LICENSE", "README.md"]
[tool.poetry.dependencies]
python = "^3.7"
python = "^3.8"
fastapi = "*"
uvicorn = "*"
redis = { version = "^4.2.0rc1", optional = true }
aiomcache = { version = "*", optional = true }
pendulum = "*"
aiobotocore = { version = ">=1.4.1,<3.0.0", optional = true }
typing-extensions = { version = ">=4.1.0" }
importlib-metadata = { version = "^6.6.0", python = "<3.8" }
pendulum = "^3.0.0"
aiomcache = { version = "^0.8.2", optional = true }
aiobotocore = {version = "^2.13.1", optional = true}
[tool.poetry.group.linting]
optional = true
[tool.poetry.group.linting.dependencies]
mypy = { version = "^1.2.0", python = "^3.10" }
pyright = { version = "^1.1.306", python = "^3.10" }
pyright = { version = "^1.1.373", python = "^3.10" }
types-aiobotocore = { extras = ["dynamodb"], version = "^2.5.0.post2", python = "^3.10" }
types-redis = { version = "^4.5.4.2", python = "^3.10" }
ruff = { version = ">=0.0.267,<0.1.2", python = "^3.10" }
@@ -57,7 +57,7 @@ all = ["redis", "aiomcache", "aiobotocore"]
[tool.mypy]
files = ["."]
python_version = "3.7"
python_version = "3.8"
# equivalent of --strict
warn_unused_configs = true
disallow_any_generics = true
@@ -72,7 +72,7 @@ warn_unused_ignores = true
warn_return_any = true
no_implicit_reexport = true
strict_equality = true
strict_concatenate = true
extra_checks = true
[[tool.mypy.overrides]]
module = "examples.*.main"
@@ -90,7 +90,7 @@ issue_format = "[#{issue}](https://github.com/long2ice/fastapi-cache/issues/{iss
[tool.pyright]
strict = ["fastapi_cache", "tests"]
pythonVersion = "3.7"
pythonVersion = "3.8"
[tool.pytest.ini_options]
addopts = "-p no:warnings"
@@ -108,7 +108,7 @@ select = [
"W", # pycodestyle warnings
"UP", # pyupgrade
]
target-version = "py37"
target-version = "py38"
[build-system]
requires = ["poetry-core"]

View File

@@ -22,19 +22,19 @@ def test_datetime() -> None:
response = client.get("/datetime")
assert response.headers.get("X-FastAPI-Cache") == "MISS"
now = response.json().get("now")
now_ = pendulum.now().replace(microsecond=0) # type: ignore[no-untyped-call]
assert pendulum.parse(now).replace(microsecond=0) == now_ # type: ignore[attr-defined]
now_ = pendulum.now()
assert pendulum.parse(now) == now_
response = client.get("/datetime")
assert response.headers.get("X-FastAPI-Cache") == "HIT"
now = response.json().get("now")
assert pendulum.parse(now).replace(microsecond=0) == now_ # type: ignore[attr-defined]
assert pendulum.parse(now) == now_
time.sleep(3)
response = client.get("/datetime")
now = response.json().get("now")
assert response.headers.get("X-FastAPI-Cache") == "MISS"
now = pendulum.parse(now).replace(microsecond=0) # type: ignore[attr-defined]
now = pendulum.parse(now)
assert now != now_
assert now == pendulum.now().replace(microsecond=0) # type: ignore[no-untyped-call]
assert now == pendulum.now()
def test_date() -> None:
@@ -42,18 +42,18 @@ def test_date() -> None:
with TestClient(app) as client:
response = client.get("/date")
assert response.headers.get("X-FastAPI-Cache") == "MISS"
assert pendulum.parse(response.json()) == pendulum.today() # type: ignore[attr-defined]
assert pendulum.parse(response.json()) == pendulum.today()
# do it again to test cache
response = client.get("/date")
assert response.headers.get("X-FastAPI-Cache") == "HIT"
assert pendulum.parse(response.json()) == pendulum.today() # type: ignore[attr-defined]
assert pendulum.parse(response.json()) == pendulum.today()
# now test with cache disabled, as that's a separate code path
FastAPICache._enable = False # pyright: ignore[reportPrivateUsage]
response = client.get("/date")
assert "X-FastAPI-Cache" not in response.headers
assert pendulum.parse(response.json()) == pendulum.today() # type: ignore[attr-defined]
assert pendulum.parse(response.json()) == pendulum.today()
FastAPICache._enable = True # pyright: ignore[reportPrivateUsage]