Coverage for tests/test_dependency_wrapped.py: 100%

223 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2025-12-04 08:29 +0000

1import inspect 1abcdefg

2import sys 1abcdefg

3from functools import wraps 1abcdefg

4from typing import AsyncGenerator, Generator 1abcdefg

5 

6import pytest 1abcdefg

7from fastapi import Depends, FastAPI 1abcdefg

8from fastapi.concurrency import iterate_in_threadpool, run_in_threadpool 1abcdefg

9from fastapi.testclient import TestClient 1abcdefg

10 

11if sys.version_info >= (3, 13): # pragma: no cover 1abcdefg

12 from inspect import iscoroutinefunction 1fg

13else: # pragma: no cover 

14 from asyncio import iscoroutinefunction 1abcde

15 

16 

17def noop_wrap(func): 1abcdefg

18 @wraps(func) 1abcdefg

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

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

21 

22 return wrapper 1abcdefg

23 

24 

25def noop_wrap_async(func): 1abcdefg

26 if inspect.isgeneratorfunction(func): 1abcdefg

27 

28 @wraps(func) 1abcdefg

29 async def gen_wrapper(*args, **kwargs): 1abcdefg

30 async for item in iterate_in_threadpool(func(*args, **kwargs)): 1hijklmn

31 yield item 1hijklmn

32 

33 return gen_wrapper 1abcdefg

34 

35 elif inspect.isasyncgenfunction(func): 1abcdefg

36 

37 @wraps(func) 1abcdefg

38 async def async_gen_wrapper(*args, **kwargs): 1abcdefg

39 async for item in func(*args, **kwargs): 1hijklmn

40 yield item 1hijklmn

41 

42 return async_gen_wrapper 1abcdefg

43 

44 @wraps(func) 1abcdefg

45 async def wrapper(*args, **kwargs): 1abcdefg

46 if inspect.isroutine(func) and iscoroutinefunction(func): 1hijklmn

47 return await func(*args, **kwargs) 1hijklmn

48 if inspect.isclass(func): 1hijklmn

49 return await run_in_threadpool(func, *args, **kwargs) 1hijklmn

50 dunder_call = getattr(func, "__call__", None) # noqa: B004 1hijklmn

51 if iscoroutinefunction(dunder_call): 1hijklmn

52 return await dunder_call(*args, **kwargs) 1hijklmn

53 return await run_in_threadpool(func, *args, **kwargs) 1hijklmn

54 

55 return wrapper 1abcdefg

56 

57 

58class ClassInstanceDep: 1abcdefg

59 def __call__(self): 1abcdefg

60 return True 1hijklmn

61 

62 

63class_instance_dep = ClassInstanceDep() 1abcdefg

64wrapped_class_instance_dep = noop_wrap(class_instance_dep) 1abcdefg

65wrapped_class_instance_dep_async_wrapper = noop_wrap_async(class_instance_dep) 1abcdefg

66 

67 

68class ClassInstanceGenDep: 1abcdefg

69 def __call__(self): 1abcdefg

70 yield True 1hijklmn

71 

72 

73class_instance_gen_dep = ClassInstanceGenDep() 1abcdefg

74wrapped_class_instance_gen_dep = noop_wrap(class_instance_gen_dep) 1abcdefg

75 

76 

77class ClassInstanceWrappedDep: 1abcdefg

78 @noop_wrap 1abcdefg

79 def __call__(self): 1abcdefg

80 return True 1hijklmn

81 

82 

83class_instance_wrapped_dep = ClassInstanceWrappedDep() 1abcdefg

84 

85 

86class ClassInstanceWrappedAsyncDep: 1abcdefg

87 @noop_wrap_async 1abcdefg

88 def __call__(self): 1abcdefg

89 return True 1hijklmn

90 

91 

92class_instance_wrapped_async_dep = ClassInstanceWrappedAsyncDep() 1abcdefg

93 

94 

95class ClassInstanceWrappedGenDep: 1abcdefg

96 @noop_wrap 1abcdefg

97 def __call__(self): 1abcdefg

98 yield True 1hijklmn

99 

100 

101class_instance_wrapped_gen_dep = ClassInstanceWrappedGenDep() 1abcdefg

102 

103 

104class ClassInstanceWrappedAsyncGenDep: 1abcdefg

105 @noop_wrap_async 1abcdefg

106 def __call__(self): 1abcdefg

107 yield True 1hijklmn

108 

109 

110class_instance_wrapped_async_gen_dep = ClassInstanceWrappedAsyncGenDep() 1abcdefg

111 

112 

113class ClassDep: 1abcdefg

114 def __init__(self): 1abcdefg

115 self.value = True 1hijklmn

116 

117 

118wrapped_class_dep = noop_wrap(ClassDep) 1abcdefg

119wrapped_class_dep_async_wrapper = noop_wrap_async(ClassDep) 1abcdefg

120 

121 

122class ClassInstanceAsyncDep: 1abcdefg

123 async def __call__(self): 1abcdefg

124 return True 1hijklmn

125 

126 

127class_instance_async_dep = ClassInstanceAsyncDep() 1abcdefg

128wrapped_class_instance_async_dep = noop_wrap(class_instance_async_dep) 1abcdefg

129wrapped_class_instance_async_dep_async_wrapper = noop_wrap_async( 1abcdefg

130 class_instance_async_dep 

131) 

132 

133 

134class ClassInstanceAsyncGenDep: 1abcdefg

135 async def __call__(self): 1abcdefg

136 yield True 1hijklmn

137 

138 

139class_instance_async_gen_dep = ClassInstanceAsyncGenDep() 1abcdefg

140wrapped_class_instance_async_gen_dep = noop_wrap(class_instance_async_gen_dep) 1abcdefg

141 

142 

143class ClassInstanceAsyncWrappedDep: 1abcdefg

144 @noop_wrap 1abcdefg

145 async def __call__(self): 1abcdefg

146 return True 1hijklmn

147 

148 

149class_instance_async_wrapped_dep = ClassInstanceAsyncWrappedDep() 1abcdefg

150 

151 

152class ClassInstanceAsyncWrappedAsyncDep: 1abcdefg

153 @noop_wrap_async 1abcdefg

154 async def __call__(self): 1abcdefg

155 return True 1hijklmn

156 

157 

158class_instance_async_wrapped_async_dep = ClassInstanceAsyncWrappedAsyncDep() 1abcdefg

159 

160 

161class ClassInstanceAsyncWrappedGenDep: 1abcdefg

162 @noop_wrap 1abcdefg

163 async def __call__(self): 1abcdefg

164 yield True 1hijklmn

165 

166 

167class_instance_async_wrapped_gen_dep = ClassInstanceAsyncWrappedGenDep() 1abcdefg

168 

169 

170class ClassInstanceAsyncWrappedGenAsyncDep: 1abcdefg

171 @noop_wrap_async 1abcdefg

172 async def __call__(self): 1abcdefg

173 yield True 1hijklmn

174 

175 

176class_instance_async_wrapped_gen_async_dep = ClassInstanceAsyncWrappedGenAsyncDep() 1abcdefg

177 

178app = FastAPI() 1abcdefg

179 

180# Sync wrapper 

181 

182 

183@noop_wrap 1abcdefg

184def wrapped_dependency() -> bool: 1abcdefg

185 return True 1hijklmn

186 

187 

188@noop_wrap 1abcdefg

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

190 yield True 1hijklmn

191 

192 

193@noop_wrap 1abcdefg

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

195 return True 1hijklmn

196 

197 

198@noop_wrap 1abcdefg

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

200 yield True 1hijklmn

201 

202 

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

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

205 return value 1hijklmn

206 

207 

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

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

210 return value 1hijklmn

211 

212 

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

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

215 return value 1hijklmn

216 

217 

218@app.get("/async-wrapped-gen-dependency/") 1abcdefg

219async def get_async_wrapped_gen_dependency( 1abcdefg

220 value: bool = Depends(async_wrapped_gen_dependency), 

221): 

222 return value 1hijklmn

223 

224 

225@app.get("/wrapped-class-instance-dependency/") 1abcdefg

226async def get_wrapped_class_instance_dependency( 1abcdefg

227 value: bool = Depends(wrapped_class_instance_dep), 

228): 

229 return value 1hijklmn

230 

231 

232@app.get("/wrapped-class-instance-async-dependency/") 1abcdefg

233async def get_wrapped_class_instance_async_dependency( 1abcdefg

234 value: bool = Depends(wrapped_class_instance_async_dep), 

235): 

236 return value 1hijklmn

237 

238 

239@app.get("/wrapped-class-instance-gen-dependency/") 1abcdefg

240async def get_wrapped_class_instance_gen_dependency( 1abcdefg

241 value: bool = Depends(wrapped_class_instance_gen_dep), 

242): 

243 return value 1hijklmn

244 

245 

246@app.get("/wrapped-class-instance-async-gen-dependency/") 1abcdefg

247async def get_wrapped_class_instance_async_gen_dependency( 1abcdefg

248 value: bool = Depends(wrapped_class_instance_async_gen_dep), 

249): 

250 return value 1hijklmn

251 

252 

253@app.get("/class-instance-wrapped-dependency/") 1abcdefg

254async def get_class_instance_wrapped_dependency( 1abcdefg

255 value: bool = Depends(class_instance_wrapped_dep), 

256): 

257 return value 1hijklmn

258 

259 

260@app.get("/class-instance-wrapped-async-dependency/") 1abcdefg

261async def get_class_instance_wrapped_async_dependency( 1abcdefg

262 value: bool = Depends(class_instance_wrapped_async_dep), 

263): 

264 return value 1hijklmn

265 

266 

267@app.get("/class-instance-async-wrapped-dependency/") 1abcdefg

268async def get_class_instance_async_wrapped_dependency( 1abcdefg

269 value: bool = Depends(class_instance_async_wrapped_dep), 

270): 

271 return value 1hijklmn

272 

273 

274@app.get("/class-instance-async-wrapped-async-dependency/") 1abcdefg

275async def get_class_instance_async_wrapped_async_dependency( 1abcdefg

276 value: bool = Depends(class_instance_async_wrapped_async_dep), 

277): 

278 return value 1hijklmn

279 

280 

281@app.get("/class-instance-wrapped-gen-dependency/") 1abcdefg

282async def get_class_instance_wrapped_gen_dependency( 1abcdefg

283 value: bool = Depends(class_instance_wrapped_gen_dep), 

284): 

285 return value 1hijklmn

286 

287 

288@app.get("/class-instance-wrapped-async-gen-dependency/") 1abcdefg

289async def get_class_instance_wrapped_async_gen_dependency( 1abcdefg

290 value: bool = Depends(class_instance_wrapped_async_gen_dep), 

291): 

292 return value 1hijklmn

293 

294 

295@app.get("/class-instance-async-wrapped-gen-dependency/") 1abcdefg

296async def get_class_instance_async_wrapped_gen_dependency( 1abcdefg

297 value: bool = Depends(class_instance_async_wrapped_gen_dep), 

298): 

299 return value 1hijklmn

300 

301 

302@app.get("/class-instance-async-wrapped-gen-async-dependency/") 1abcdefg

303async def get_class_instance_async_wrapped_gen_async_dependency( 1abcdefg

304 value: bool = Depends(class_instance_async_wrapped_gen_async_dep), 

305): 

306 return value 1hijklmn

307 

308 

309@app.get("/wrapped-class-dependency/") 1abcdefg

310async def get_wrapped_class_dependency(value: ClassDep = Depends(wrapped_class_dep)): 1abcdefg

311 return value.value 1hijklmn

312 

313 

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

315@noop_wrap 1abcdefg

316def get_wrapped_endpoint(): 1abcdefg

317 return True 1hijklmn

318 

319 

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

321@noop_wrap 1abcdefg

322async def get_async_wrapped_endpoint(): 1abcdefg

323 return True 1hijklmn

324 

325 

326# Async wrapper 

327 

328 

329@noop_wrap_async 1abcdefg

330def wrapped_dependency_async_wrapper() -> bool: 1abcdefg

331 return True 1hijklmn

332 

333 

334@noop_wrap_async 1abcdefg

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

336 yield True 1hijklmn

337 

338 

339@noop_wrap_async 1abcdefg

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

341 return True 1hijklmn

342 

343 

344@noop_wrap_async 1abcdefg

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

346 yield True 1hijklmn

347 

348 

349@app.get("/wrapped-dependency-async-wrapper/") 1abcdefg

350async def get_wrapped_dependency_async_wrapper( 1abcdefg

351 value: bool = Depends(wrapped_dependency_async_wrapper), 

352): 

353 return value 1hijklmn

354 

355 

356@app.get("/wrapped-gen-dependency-async-wrapper/") 1abcdefg

357async def get_wrapped_gen_dependency_async_wrapper( 1abcdefg

358 value: bool = Depends(wrapped_gen_dependency_async_wrapper), 

359): 

360 return value 1hijklmn

361 

362 

363@app.get("/async-wrapped-dependency-async-wrapper/") 1abcdefg

364async def get_async_wrapped_dependency_async_wrapper( 1abcdefg

365 value: bool = Depends(async_wrapped_dependency_async_wrapper), 

366): 

367 return value 1hijklmn

368 

369 

370@app.get("/async-wrapped-gen-dependency-async-wrapper/") 1abcdefg

371async def get_async_wrapped_gen_dependency_async_wrapper( 1abcdefg

372 value: bool = Depends(async_wrapped_gen_dependency_async_wrapper), 

373): 

374 return value 1hijklmn

375 

376 

377@app.get("/wrapped-class-instance-dependency-async-wrapper/") 1abcdefg

378async def get_wrapped_class_instance_dependency_async_wrapper( 1abcdefg

379 value: bool = Depends(wrapped_class_instance_dep_async_wrapper), 

380): 

381 return value 1hijklmn

382 

383 

384@app.get("/wrapped-class-instance-async-dependency-async-wrapper/") 1abcdefg

385async def get_wrapped_class_instance_async_dependency_async_wrapper( 1abcdefg

386 value: bool = Depends(wrapped_class_instance_async_dep_async_wrapper), 

387): 

388 return value 1hijklmn

389 

390 

391@app.get("/wrapped-class-dependency-async-wrapper/") 1abcdefg

392async def get_wrapped_class_dependency_async_wrapper( 1abcdefg

393 value: ClassDep = Depends(wrapped_class_dep_async_wrapper), 

394): 

395 return value.value 1hijklmn

396 

397 

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

399@noop_wrap_async 1abcdefg

400def get_wrapped_endpoint_async_wrapper(): 1abcdefg

401 return True 1hijklmn

402 

403 

404@app.get("/async-wrapped-endpoint-async-wrapper/") 1abcdefg

405@noop_wrap_async 1abcdefg

406async def get_async_wrapped_endpoint_async_wrapper(): 1abcdefg

407 return True 1hijklmn

408 

409 

410client = TestClient(app) 1abcdefg

411 

412 

413@pytest.mark.parametrize( 1abcdefg

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): 1abcdefg

447 response = client.get(route) 1hijklmn

448 assert response.status_code == 200, response.text 1hijklmn

449 assert response.json() is True 1hijklmn