Files
fastapi-cache/examples/in_memory/main.py
Martijn Pieters 013be85f97 Typing cleanup
- Compatibility with older Python versions
  - use `Optional` and `Union` instead of `... | None` and `a | b`
  - use `typing_extensions.Protocol` instead of `typing.Protocol`
  - use `typing.Dict`, `typing.List`, etc. instead of the concrete types.

- Fix backend `.get()` annotations; not all were marked as `Optional[str]`
- Don't return anything from `Backend.set()` methods.
- The `Coder.decode_as_type()` type parameter must be a type to be
  compatible with `ModelField(..., type_=...)`.
- Clean up `Optional[]` use, remove where it is not needed.
- Clean up variable use in decorator, keeping the raw cached value
  separate from the return value from the wrapped endpoint.
- Annotate the wrapper as returning either the original type _or_ a
  Response (returning a 304 Not Modified response).
- Clean up small edge-case where `response` could be `None`.
- Correct type annotation on `JsonCoder.decode()` to match `Coder.decode()`.
2023-05-11 12:31:05 +01:00

129 lines
2.9 KiB
Python

from typing import Dict, Optional
import pendulum
import uvicorn
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import JSONResponse, Response
from fastapi_cache import FastAPICache
from fastapi_cache.backends.inmemory import InMemoryBackend
from fastapi_cache.decorator import cache
from pydantic import BaseModel
app = FastAPI()
ret = 0
@cache(namespace="test", expire=1)
async def get_ret():
global ret
ret = ret + 1
return ret
@app.get("/")
@cache(namespace="test", expire=10)
async def index():
return dict(ret=await get_ret())
@app.get("/clear")
async def clear():
return await FastAPICache.clear(namespace="test")
@app.get("/date")
@cache(namespace="test", expire=10)
async def get_date():
return pendulum.today()
@app.get("/datetime")
@cache(namespace="test", expire=2)
async def get_datetime(request: Request, response: Response):
return {"now": pendulum.now()}
@cache(namespace="test")
async def func_kwargs(*unused_args, **kwargs):
return kwargs
@app.get("/kwargs")
async def get_kwargs(name: str):
return await func_kwargs(name, name=name)
@app.get("/sync-me")
@cache(namespace="test")
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.
return 42
@app.get("/cache_response_obj")
@cache(namespace="test", expire=5)
async def cache_response_obj():
return JSONResponse({"a": 1})
class SomeClass:
def __init__(self, value):
self.value = value
async def handler_method(self):
return self.value
# register an instance method as a handler
instance = SomeClass(17)
app.get("/method")(cache(namespace="test")(instance.handler_method))
# cache a Pydantic model instance; the return type annotation is required in this case
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.get("/pydantic_instance")
@cache(namespace="test", expire=5)
async def pydantic_instance() -> Item:
return Item(name="Something", description="An instance of a Pydantic model", price=10.5)
put_ret = 0
@app.put("/uncached_put")
@cache(namespace="test", expire=5)
async def uncached_put():
global put_ret
put_ret = put_ret + 1
return {"value": put_ret}
@app.get("/namespaced_injection")
@cache(namespace="test", expire=5, injected_dependency_namespace="monty_python")
def namespaced_injection(
__fastapi_cache_request: int = 42, __fastapi_cache_response: int = 17
) -> Dict[str, int]:
return {
"__fastapi_cache_request": __fastapi_cache_request,
"__fastapi_cache_response": __fastapi_cache_response,
}
@app.on_event("startup")
async def startup():
FastAPICache.init(InMemoryBackend())
if __name__ == "__main__":
uvicorn.run("main:app", debug=True, reload=True)