MCPcopy
hub / github.com/long2ice/fastapi-cache / wrapper

Function wrapper

fastapi_cache/decorator.py:116–229  ·  view source on GitHub ↗
(
        func: Callable[P, Awaitable[R]]
    )

Source from the content-addressed store, hash-verified

114 )
115
116 def wrapper(
117 func: Callable[P, Awaitable[R]]
118 ) -> Callable[P, Awaitable[Union[R, Response]]]:
119 # get_typed_signature ensures that any forward references are resolved first
120 wrapped_signature = get_typed_signature(func)
121 to_inject: List[Parameter] = []
122 request_param = _locate_param(wrapped_signature, injected_request, to_inject)
123 response_param = _locate_param(wrapped_signature, injected_response, to_inject)
124 return_type = get_typed_return_annotation(func)
125
126 @wraps(func)
127 async def inner(*args: P.args, **kwargs: P.kwargs) -> Union[R, Response]:
128 nonlocal coder
129 nonlocal expire
130 nonlocal key_builder
131
132 async def ensure_async_func(*args: P.args, **kwargs: P.kwargs) -> R:
133 """Run cached sync functions in thread pool just like FastAPI."""
134 # if the wrapped function does NOT have request or response in
135 # its function signature, make sure we don't pass them in as
136 # keyword arguments
137 kwargs.pop(injected_request.name, None)
138 kwargs.pop(injected_response.name, None)
139
140 if iscoroutinefunction(func):
141 # async, return as is.
142 # unintuitively, we have to await once here, so that caller
143 # does not have to await twice. See
144 # https://stackoverflow.com/a/59268198/532513
145 return await func(*args, **kwargs)
146 else:
147 # sync, wrap in thread and return async
148 # see above why we have to await even although caller also awaits.
149 return await run_in_threadpool(func, *args, **kwargs) # type: ignore[arg-type]
150
151 copy_kwargs = kwargs.copy()
152 request: Optional[Request] = copy_kwargs.pop(request_param.name, None) # type: ignore[assignment]
153 response: Optional[Response] = copy_kwargs.pop(response_param.name, None) # type: ignore[assignment]
154
155 if _uncacheable(request):
156 return await ensure_async_func(*args, **kwargs)
157
158 prefix = FastAPICache.get_prefix()
159 coder = coder or FastAPICache.get_coder()
160 expire = expire or FastAPICache.get_expire()
161 key_builder = key_builder or FastAPICache.get_key_builder()
162 backend = FastAPICache.get_backend()
163 cache_status_header = FastAPICache.get_cache_status_header()
164
165 cache_key = key_builder(
166 func,
167 f"{prefix}:{namespace}",
168 request=request,
169 response=response,
170 args=args,
171 kwargs=copy_kwargs,
172 )
173 if isawaitable(cache_key):

Callers

nothing calls this directly

Calls 2

_locate_paramFunction · 0.85
_augment_signatureFunction · 0.85

Tested by

no test coverage detected