Coverage for tests / test_dependency_wrapped.py: 100%
223 statements
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
« prev ^ index » next coverage.py v7.13.3, created at 2026-02-12 18:15 +0000
1import inspect 1abcd
2import sys 1abcd
3from collections.abc import AsyncGenerator, Generator 1abcd
4from functools import wraps 1abcd
6import pytest 1abcd
7from fastapi import Depends, FastAPI 1abcd
8from fastapi.concurrency import iterate_in_threadpool, run_in_threadpool 1abcd
9from fastapi.testclient import TestClient 1abcd
11if sys.version_info >= (3, 13): # pragma: no cover 1abcd
12 from inspect import iscoroutinefunction 1ab
13else: # pragma: no cover
14 from asyncio import iscoroutinefunction 1cd
17def noop_wrap(func): 1abcd
18 @wraps(func) 1abcd
19 def wrapper(*args, **kwargs): 1abcd
20 return func(*args, **kwargs) 1efg
22 return wrapper 1abcd
25def noop_wrap_async(func): 1abcd
26 if inspect.isgeneratorfunction(func): 1abcd
28 @wraps(func) 1abcd
29 async def gen_wrapper(*args, **kwargs): 1abcd
30 async for item in iterate_in_threadpool(func(*args, **kwargs)): 1efg
31 yield item 1efg
33 return gen_wrapper 1abcd
35 elif inspect.isasyncgenfunction(func): 1abcd
37 @wraps(func) 1abcd
38 async def async_gen_wrapper(*args, **kwargs): 1abcd
39 async for item in func(*args, **kwargs): 1efg
40 yield item 1efg
42 return async_gen_wrapper 1abcd
44 @wraps(func) 1abcd
45 async def wrapper(*args, **kwargs): 1abcd
46 if inspect.isroutine(func) and iscoroutinefunction(func): 1efg
47 return await func(*args, **kwargs) 1efg
48 if inspect.isclass(func): 1efg
49 return await run_in_threadpool(func, *args, **kwargs) 1efg
50 dunder_call = getattr(func, "__call__", None) # noqa: B004 1efg
51 if iscoroutinefunction(dunder_call): 1efg
52 return await dunder_call(*args, **kwargs) 1efg
53 return await run_in_threadpool(func, *args, **kwargs) 1efg
55 return wrapper 1abcd
58class ClassInstanceDep: 1abcd
59 def __call__(self): 1abcd
60 return True 1efg
63class_instance_dep = ClassInstanceDep() 1abcd
64wrapped_class_instance_dep = noop_wrap(class_instance_dep) 1abcd
65wrapped_class_instance_dep_async_wrapper = noop_wrap_async(class_instance_dep) 1abcd
68class ClassInstanceGenDep: 1abcd
69 def __call__(self): 1abcd
70 yield True 1efg
73class_instance_gen_dep = ClassInstanceGenDep() 1abcd
74wrapped_class_instance_gen_dep = noop_wrap(class_instance_gen_dep) 1abcd
77class ClassInstanceWrappedDep: 1abcd
78 @noop_wrap 1abcd
79 def __call__(self): 1abcd
80 return True 1efg
83class_instance_wrapped_dep = ClassInstanceWrappedDep() 1abcd
86class ClassInstanceWrappedAsyncDep: 1abcd
87 @noop_wrap_async 1abcd
88 def __call__(self): 1abcd
89 return True 1efg
92class_instance_wrapped_async_dep = ClassInstanceWrappedAsyncDep() 1abcd
95class ClassInstanceWrappedGenDep: 1abcd
96 @noop_wrap 1abcd
97 def __call__(self): 1abcd
98 yield True 1efg
101class_instance_wrapped_gen_dep = ClassInstanceWrappedGenDep() 1abcd
104class ClassInstanceWrappedAsyncGenDep: 1abcd
105 @noop_wrap_async 1abcd
106 def __call__(self): 1abcd
107 yield True 1efg
110class_instance_wrapped_async_gen_dep = ClassInstanceWrappedAsyncGenDep() 1abcd
113class ClassDep: 1abcd
114 def __init__(self): 1abcd
115 self.value = True 1efg
118wrapped_class_dep = noop_wrap(ClassDep) 1abcd
119wrapped_class_dep_async_wrapper = noop_wrap_async(ClassDep) 1abcd
122class ClassInstanceAsyncDep: 1abcd
123 async def __call__(self): 1abcd
124 return True 1efg
127class_instance_async_dep = ClassInstanceAsyncDep() 1abcd
128wrapped_class_instance_async_dep = noop_wrap(class_instance_async_dep) 1abcd
129wrapped_class_instance_async_dep_async_wrapper = noop_wrap_async( 1abcd
130 class_instance_async_dep
131)
134class ClassInstanceAsyncGenDep: 1abcd
135 async def __call__(self): 1abcd
136 yield True 1efg
139class_instance_async_gen_dep = ClassInstanceAsyncGenDep() 1abcd
140wrapped_class_instance_async_gen_dep = noop_wrap(class_instance_async_gen_dep) 1abcd
143class ClassInstanceAsyncWrappedDep: 1abcd
144 @noop_wrap 1abcd
145 async def __call__(self): 1abcd
146 return True 1efg
149class_instance_async_wrapped_dep = ClassInstanceAsyncWrappedDep() 1abcd
152class ClassInstanceAsyncWrappedAsyncDep: 1abcd
153 @noop_wrap_async 1abcd
154 async def __call__(self): 1abcd
155 return True 1efg
158class_instance_async_wrapped_async_dep = ClassInstanceAsyncWrappedAsyncDep() 1abcd
161class ClassInstanceAsyncWrappedGenDep: 1abcd
162 @noop_wrap 1abcd
163 async def __call__(self): 1abcd
164 yield True 1efg
167class_instance_async_wrapped_gen_dep = ClassInstanceAsyncWrappedGenDep() 1abcd
170class ClassInstanceAsyncWrappedGenAsyncDep: 1abcd
171 @noop_wrap_async 1abcd
172 async def __call__(self): 1abcd
173 yield True 1efg
176class_instance_async_wrapped_gen_async_dep = ClassInstanceAsyncWrappedGenAsyncDep() 1abcd
178app = FastAPI() 1abcd
180# Sync wrapper
183@noop_wrap 1abcd
184def wrapped_dependency() -> bool: 1abcd
185 return True 1efg
188@noop_wrap 1abcd
189def wrapped_gen_dependency() -> Generator[bool, None, None]: 1abcd
190 yield True 1efg
193@noop_wrap 1abcd
194async def async_wrapped_dependency() -> bool: 1abcd
195 return True 1efg
198@noop_wrap 1abcd
199async def async_wrapped_gen_dependency() -> AsyncGenerator[bool, None]: 1abcd
200 yield True 1efg
203@app.get("/wrapped-dependency/") 1abcd
204async def get_wrapped_dependency(value: bool = Depends(wrapped_dependency)): 1abcd
205 return value 1efg
208@app.get("/wrapped-gen-dependency/") 1abcd
209async def get_wrapped_gen_dependency(value: bool = Depends(wrapped_gen_dependency)): 1abcd
210 return value 1efg
213@app.get("/async-wrapped-dependency/") 1abcd
214async def get_async_wrapped_dependency(value: bool = Depends(async_wrapped_dependency)): 1abcd
215 return value 1efg
218@app.get("/async-wrapped-gen-dependency/") 1abcd
219async def get_async_wrapped_gen_dependency( 1abcd
220 value: bool = Depends(async_wrapped_gen_dependency),
221):
222 return value 1efg
225@app.get("/wrapped-class-instance-dependency/") 1abcd
226async def get_wrapped_class_instance_dependency( 1abcd
227 value: bool = Depends(wrapped_class_instance_dep),
228):
229 return value 1efg
232@app.get("/wrapped-class-instance-async-dependency/") 1abcd
233async def get_wrapped_class_instance_async_dependency( 1abcd
234 value: bool = Depends(wrapped_class_instance_async_dep),
235):
236 return value 1efg
239@app.get("/wrapped-class-instance-gen-dependency/") 1abcd
240async def get_wrapped_class_instance_gen_dependency( 1abcd
241 value: bool = Depends(wrapped_class_instance_gen_dep),
242):
243 return value 1efg
246@app.get("/wrapped-class-instance-async-gen-dependency/") 1abcd
247async def get_wrapped_class_instance_async_gen_dependency( 1abcd
248 value: bool = Depends(wrapped_class_instance_async_gen_dep),
249):
250 return value 1efg
253@app.get("/class-instance-wrapped-dependency/") 1abcd
254async def get_class_instance_wrapped_dependency( 1abcd
255 value: bool = Depends(class_instance_wrapped_dep),
256):
257 return value 1efg
260@app.get("/class-instance-wrapped-async-dependency/") 1abcd
261async def get_class_instance_wrapped_async_dependency( 1abcd
262 value: bool = Depends(class_instance_wrapped_async_dep),
263):
264 return value 1efg
267@app.get("/class-instance-async-wrapped-dependency/") 1abcd
268async def get_class_instance_async_wrapped_dependency( 1abcd
269 value: bool = Depends(class_instance_async_wrapped_dep),
270):
271 return value 1efg
274@app.get("/class-instance-async-wrapped-async-dependency/") 1abcd
275async def get_class_instance_async_wrapped_async_dependency( 1abcd
276 value: bool = Depends(class_instance_async_wrapped_async_dep),
277):
278 return value 1efg
281@app.get("/class-instance-wrapped-gen-dependency/") 1abcd
282async def get_class_instance_wrapped_gen_dependency( 1abcd
283 value: bool = Depends(class_instance_wrapped_gen_dep),
284):
285 return value 1efg
288@app.get("/class-instance-wrapped-async-gen-dependency/") 1abcd
289async def get_class_instance_wrapped_async_gen_dependency( 1abcd
290 value: bool = Depends(class_instance_wrapped_async_gen_dep),
291):
292 return value 1efg
295@app.get("/class-instance-async-wrapped-gen-dependency/") 1abcd
296async def get_class_instance_async_wrapped_gen_dependency( 1abcd
297 value: bool = Depends(class_instance_async_wrapped_gen_dep),
298):
299 return value 1efg
302@app.get("/class-instance-async-wrapped-gen-async-dependency/") 1abcd
303async def get_class_instance_async_wrapped_gen_async_dependency( 1abcd
304 value: bool = Depends(class_instance_async_wrapped_gen_async_dep),
305):
306 return value 1efg
309@app.get("/wrapped-class-dependency/") 1abcd
310async def get_wrapped_class_dependency(value: ClassDep = Depends(wrapped_class_dep)): 1abcd
311 return value.value 1efg
314@app.get("/wrapped-endpoint/") 1abcd
315@noop_wrap 1abcd
316def get_wrapped_endpoint(): 1abcd
317 return True 1efg
320@app.get("/async-wrapped-endpoint/") 1abcd
321@noop_wrap 1abcd
322async def get_async_wrapped_endpoint(): 1abcd
323 return True 1efg
326# Async wrapper
329@noop_wrap_async 1abcd
330def wrapped_dependency_async_wrapper() -> bool: 1abcd
331 return True 1efg
334@noop_wrap_async 1abcd
335def wrapped_gen_dependency_async_wrapper() -> Generator[bool, None, None]: 1abcd
336 yield True 1efg
339@noop_wrap_async 1abcd
340async def async_wrapped_dependency_async_wrapper() -> bool: 1abcd
341 return True 1efg
344@noop_wrap_async 1abcd
345async def async_wrapped_gen_dependency_async_wrapper() -> AsyncGenerator[bool, None]: 1abcd
346 yield True 1efg
349@app.get("/wrapped-dependency-async-wrapper/") 1abcd
350async def get_wrapped_dependency_async_wrapper( 1abcd
351 value: bool = Depends(wrapped_dependency_async_wrapper),
352):
353 return value 1efg
356@app.get("/wrapped-gen-dependency-async-wrapper/") 1abcd
357async def get_wrapped_gen_dependency_async_wrapper( 1abcd
358 value: bool = Depends(wrapped_gen_dependency_async_wrapper),
359):
360 return value 1efg
363@app.get("/async-wrapped-dependency-async-wrapper/") 1abcd
364async def get_async_wrapped_dependency_async_wrapper( 1abcd
365 value: bool = Depends(async_wrapped_dependency_async_wrapper),
366):
367 return value 1efg
370@app.get("/async-wrapped-gen-dependency-async-wrapper/") 1abcd
371async def get_async_wrapped_gen_dependency_async_wrapper( 1abcd
372 value: bool = Depends(async_wrapped_gen_dependency_async_wrapper),
373):
374 return value 1efg
377@app.get("/wrapped-class-instance-dependency-async-wrapper/") 1abcd
378async def get_wrapped_class_instance_dependency_async_wrapper( 1abcd
379 value: bool = Depends(wrapped_class_instance_dep_async_wrapper),
380):
381 return value 1efg
384@app.get("/wrapped-class-instance-async-dependency-async-wrapper/") 1abcd
385async def get_wrapped_class_instance_async_dependency_async_wrapper( 1abcd
386 value: bool = Depends(wrapped_class_instance_async_dep_async_wrapper),
387):
388 return value 1efg
391@app.get("/wrapped-class-dependency-async-wrapper/") 1abcd
392async def get_wrapped_class_dependency_async_wrapper( 1abcd
393 value: ClassDep = Depends(wrapped_class_dep_async_wrapper),
394):
395 return value.value 1efg
398@app.get("/wrapped-endpoint-async-wrapper/") 1abcd
399@noop_wrap_async 1abcd
400def get_wrapped_endpoint_async_wrapper(): 1abcd
401 return True 1efg
404@app.get("/async-wrapped-endpoint-async-wrapper/") 1abcd
405@noop_wrap_async 1abcd
406async def get_async_wrapped_endpoint_async_wrapper(): 1abcd
407 return True 1efg
410client = TestClient(app) 1abcd
413@pytest.mark.parametrize( 1abcd
414 "route",
415 [
416 "/wrapped-dependency/",
417 "/wrapped-gen-dependency/",
418 "/async-wrapped-dependency/",
419 "/async-wrapped-gen-dependency/",
420 "/wrapped-class-instance-dependency/",
421 "/wrapped-class-instance-async-dependency/",
422 "/wrapped-class-instance-gen-dependency/",
423 "/wrapped-class-instance-async-gen-dependency/",
424 "/class-instance-wrapped-dependency/",
425 "/class-instance-wrapped-async-dependency/",
426 "/class-instance-async-wrapped-dependency/",
427 "/class-instance-async-wrapped-async-dependency/",
428 "/class-instance-wrapped-gen-dependency/",
429 "/class-instance-wrapped-async-gen-dependency/",
430 "/class-instance-async-wrapped-gen-dependency/",
431 "/class-instance-async-wrapped-gen-async-dependency/",
432 "/wrapped-class-dependency/",
433 "/wrapped-endpoint/",
434 "/async-wrapped-endpoint/",
435 "/wrapped-dependency-async-wrapper/",
436 "/wrapped-gen-dependency-async-wrapper/",
437 "/async-wrapped-dependency-async-wrapper/",
438 "/async-wrapped-gen-dependency-async-wrapper/",
439 "/wrapped-class-instance-dependency-async-wrapper/",
440 "/wrapped-class-instance-async-dependency-async-wrapper/",
441 "/wrapped-class-dependency-async-wrapper/",
442 "/wrapped-endpoint-async-wrapper/",
443 "/async-wrapped-endpoint-async-wrapper/",
444 ],
445)
446def test_class_dependency(route): 1abcd
447 response = client.get(route) 1efg
448 assert response.status_code == 200, response.text 1efg
449 assert response.json() is True 1efg