Add default config when init

update JsonEncoder
This commit is contained in:
long2ice
2020-10-16 16:55:33 +08:00
parent c0259bc699
commit dc2ac9cc90
7 changed files with 153 additions and 65 deletions

View File

@@ -1,17 +1,34 @@
from typing import Callable
from fastapi_cache.coder import Coder, JsonCoder
from fastapi_cache.key_builder import default_key_builder
class FastAPICache:
_backend = None
_prefix = None
_expire = None
_init = False
_coder = None
_key_builder = None
@classmethod
def init(cls, backend, prefix: str = "", expire: int = None):
def init(
cls,
backend,
prefix: str = "",
expire: int = None,
coder: Coder = JsonCoder,
key_builder: Callable = default_key_builder,
):
if cls._init:
return
cls._init = True
cls._backend = backend
cls._prefix = prefix
cls._expire = expire
cls._coder = coder
cls._key_builder = key_builder
@classmethod
def get_backend(cls):
@@ -25,3 +42,11 @@ class FastAPICache:
@classmethod
def get_expire(cls):
return cls._expire
@classmethod
def get_coder(cls):
return cls._coder
@classmethod
def get_key_builder(cls):
return cls._key_builder

View File

@@ -1,7 +1,40 @@
import datetime
import json
import pickle # nosec:B403
from decimal import Decimal
from typing import Any
import dateutil.parser
CONVERTERS = {
"date": dateutil.parser.parse,
"datetime": dateutil.parser.parse,
"decimal": Decimal,
}
class JsonEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return {"val": obj.strftime("%Y-%m-%d %H:%M:%S"), "_spec_type": "datetime"}
elif isinstance(obj, datetime.date):
return {"val": obj.strftime("%Y-%m-%d"), "_spec_type": "date"}
elif isinstance(obj, Decimal):
return {"val": str(obj), "_spec_type": "decimal"}
else:
return super().default(obj)
def object_hook(obj):
_spec_type = obj.get("_spec_type")
if not _spec_type:
return obj
if _spec_type in CONVERTERS:
return CONVERTERS[_spec_type](obj["val"])
else:
raise TypeError("Unknown {}".format(_spec_type))
class Coder:
@classmethod
@@ -16,11 +49,11 @@ class Coder:
class JsonCoder(Coder):
@classmethod
def encode(cls, value: Any):
return json.dumps(value)
return json.dumps(value, cls=JsonEncoder)
@classmethod
def decode(cls, value: Any):
return json.loads(value)
return json.loads(value, object_hook=object_hook)
class PickleCoder(Coder):

View File

@@ -1,30 +1,14 @@
from functools import wraps
from typing import Callable, Optional, Type
from starlette.requests import Request
from starlette.responses import Response
from fastapi_cache import FastAPICache
from fastapi_cache.coder import Coder, JsonCoder
def default_key_builder(
func,
namespace: Optional[str] = "",
request: Request = None,
response: Response = None,
*args,
**kwargs,
):
prefix = FastAPICache.get_prefix()
cache_key = f"{prefix}:{namespace}:{func.__module__}:{func.__name__}:{args}:{kwargs}"
return cache_key
from fastapi_cache.coder import Coder
def cache(
expire: int = None,
coder: Type[Coder] = JsonCoder,
key_builder: Callable = default_key_builder,
coder: Type[Coder] = None,
key_builder: Callable = None,
namespace: Optional[str] = "",
):
"""
@@ -39,6 +23,13 @@ def cache(
def wrapper(func):
@wraps(func)
async def inner(*args, **kwargs):
nonlocal coder
nonlocal expire
nonlocal key_builder
coder = coder or FastAPICache.get_coder()
expire = expire or FastAPICache.get_expire()
key_builder = key_builder or FastAPICache.get_key_builder()
request = kwargs.get("request")
backend = FastAPICache.get_backend()
cache_key = key_builder(func, namespace, *args, **kwargs)

View File

@@ -0,0 +1,19 @@
from typing import Optional
from starlette.requests import Request
from starlette.responses import Response
def default_key_builder(
func,
namespace: Optional[str] = "",
request: Request = None,
response: Response = None,
*args,
**kwargs,
):
from fastapi_cache import FastAPICache
prefix = FastAPICache.get_prefix()
cache_key = f"{prefix}:{namespace}:{func.__module__}:{func.__name__}:{args}:{kwargs}"
return cache_key