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

1import inspect 1abcd

2import sys 1abcd

3from collections.abc import AsyncGenerator, Generator 1abcd

4from functools import wraps 1abcd

5 

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

10 

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

15 

16 

17def noop_wrap(func): 1abcd

18 @wraps(func) 1abcd

19 def wrapper(*args, **kwargs): 1abcd

20 return func(*args, **kwargs) 1efg

21 

22 return wrapper 1abcd

23 

24 

25def noop_wrap_async(func): 1abcd

26 if inspect.isgeneratorfunction(func): 1abcd

27 

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

32 

33 return gen_wrapper 1abcd

34 

35 elif inspect.isasyncgenfunction(func): 1abcd

36 

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

41 

42 return async_gen_wrapper 1abcd

43 

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

54 

55 return wrapper 1abcd

56 

57 

58class ClassInstanceDep: 1abcd

59 def __call__(self): 1abcd

60 return True 1efg

61 

62 

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

66 

67 

68class ClassInstanceGenDep: 1abcd

69 def __call__(self): 1abcd

70 yield True 1efg

71 

72 

73class_instance_gen_dep = ClassInstanceGenDep() 1abcd

74wrapped_class_instance_gen_dep = noop_wrap(class_instance_gen_dep) 1abcd

75 

76 

77class ClassInstanceWrappedDep: 1abcd

78 @noop_wrap 1abcd

79 def __call__(self): 1abcd

80 return True 1efg

81 

82 

83class_instance_wrapped_dep = ClassInstanceWrappedDep() 1abcd

84 

85 

86class ClassInstanceWrappedAsyncDep: 1abcd

87 @noop_wrap_async 1abcd

88 def __call__(self): 1abcd

89 return True 1efg

90 

91 

92class_instance_wrapped_async_dep = ClassInstanceWrappedAsyncDep() 1abcd

93 

94 

95class ClassInstanceWrappedGenDep: 1abcd

96 @noop_wrap 1abcd

97 def __call__(self): 1abcd

98 yield True 1efg

99 

100 

101class_instance_wrapped_gen_dep = ClassInstanceWrappedGenDep() 1abcd

102 

103 

104class ClassInstanceWrappedAsyncGenDep: 1abcd

105 @noop_wrap_async 1abcd

106 def __call__(self): 1abcd

107 yield True 1efg

108 

109 

110class_instance_wrapped_async_gen_dep = ClassInstanceWrappedAsyncGenDep() 1abcd

111 

112 

113class ClassDep: 1abcd

114 def __init__(self): 1abcd

115 self.value = True 1efg

116 

117 

118wrapped_class_dep = noop_wrap(ClassDep) 1abcd

119wrapped_class_dep_async_wrapper = noop_wrap_async(ClassDep) 1abcd

120 

121 

122class ClassInstanceAsyncDep: 1abcd

123 async def __call__(self): 1abcd

124 return True 1efg

125 

126 

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) 

132 

133 

134class ClassInstanceAsyncGenDep: 1abcd

135 async def __call__(self): 1abcd

136 yield True 1efg

137 

138 

139class_instance_async_gen_dep = ClassInstanceAsyncGenDep() 1abcd

140wrapped_class_instance_async_gen_dep = noop_wrap(class_instance_async_gen_dep) 1abcd

141 

142 

143class ClassInstanceAsyncWrappedDep: 1abcd

144 @noop_wrap 1abcd

145 async def __call__(self): 1abcd

146 return True 1efg

147 

148 

149class_instance_async_wrapped_dep = ClassInstanceAsyncWrappedDep() 1abcd

150 

151 

152class ClassInstanceAsyncWrappedAsyncDep: 1abcd

153 @noop_wrap_async 1abcd

154 async def __call__(self): 1abcd

155 return True 1efg

156 

157 

158class_instance_async_wrapped_async_dep = ClassInstanceAsyncWrappedAsyncDep() 1abcd

159 

160 

161class ClassInstanceAsyncWrappedGenDep: 1abcd

162 @noop_wrap 1abcd

163 async def __call__(self): 1abcd

164 yield True 1efg

165 

166 

167class_instance_async_wrapped_gen_dep = ClassInstanceAsyncWrappedGenDep() 1abcd

168 

169 

170class ClassInstanceAsyncWrappedGenAsyncDep: 1abcd

171 @noop_wrap_async 1abcd

172 async def __call__(self): 1abcd

173 yield True 1efg

174 

175 

176class_instance_async_wrapped_gen_async_dep = ClassInstanceAsyncWrappedGenAsyncDep() 1abcd

177 

178app = FastAPI() 1abcd

179 

180# Sync wrapper 

181 

182 

183@noop_wrap 1abcd

184def wrapped_dependency() -> bool: 1abcd

185 return True 1efg

186 

187 

188@noop_wrap 1abcd

189def wrapped_gen_dependency() -> Generator[bool, None, None]: 1abcd

190 yield True 1efg

191 

192 

193@noop_wrap 1abcd

194async def async_wrapped_dependency() -> bool: 1abcd

195 return True 1efg

196 

197 

198@noop_wrap 1abcd

199async def async_wrapped_gen_dependency() -> AsyncGenerator[bool, None]: 1abcd

200 yield True 1efg

201 

202 

203@app.get("/wrapped-dependency/") 1abcd

204async def get_wrapped_dependency(value: bool = Depends(wrapped_dependency)): 1abcd

205 return value 1efg

206 

207 

208@app.get("/wrapped-gen-dependency/") 1abcd

209async def get_wrapped_gen_dependency(value: bool = Depends(wrapped_gen_dependency)): 1abcd

210 return value 1efg

211 

212 

213@app.get("/async-wrapped-dependency/") 1abcd

214async def get_async_wrapped_dependency(value: bool = Depends(async_wrapped_dependency)): 1abcd

215 return value 1efg

216 

217 

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

223 

224 

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

230 

231 

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

237 

238 

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

244 

245 

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

251 

252 

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

258 

259 

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

265 

266 

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

272 

273 

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

279 

280 

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

286 

287 

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

293 

294 

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

300 

301 

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

307 

308 

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

312 

313 

314@app.get("/wrapped-endpoint/") 1abcd

315@noop_wrap 1abcd

316def get_wrapped_endpoint(): 1abcd

317 return True 1efg

318 

319 

320@app.get("/async-wrapped-endpoint/") 1abcd

321@noop_wrap 1abcd

322async def get_async_wrapped_endpoint(): 1abcd

323 return True 1efg

324 

325 

326# Async wrapper 

327 

328 

329@noop_wrap_async 1abcd

330def wrapped_dependency_async_wrapper() -> bool: 1abcd

331 return True 1efg

332 

333 

334@noop_wrap_async 1abcd

335def wrapped_gen_dependency_async_wrapper() -> Generator[bool, None, None]: 1abcd

336 yield True 1efg

337 

338 

339@noop_wrap_async 1abcd

340async def async_wrapped_dependency_async_wrapper() -> bool: 1abcd

341 return True 1efg

342 

343 

344@noop_wrap_async 1abcd

345async def async_wrapped_gen_dependency_async_wrapper() -> AsyncGenerator[bool, None]: 1abcd

346 yield True 1efg

347 

348 

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

354 

355 

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

361 

362 

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

368 

369 

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

375 

376 

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

382 

383 

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

389 

390 

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

396 

397 

398@app.get("/wrapped-endpoint-async-wrapper/") 1abcd

399@noop_wrap_async 1abcd

400def get_wrapped_endpoint_async_wrapper(): 1abcd

401 return True 1efg

402 

403 

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

408 

409 

410client = TestClient(app) 1abcd

411 

412 

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