Coverage for fastapi/concurrency.py: 100%

18 statements  

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

1from contextlib import asynccontextmanager as asynccontextmanager 1abcdefg

2from typing import AsyncGenerator, ContextManager, TypeVar 1abcdefg

3 

4import anyio.to_thread 1abcdefg

5from anyio import CapacityLimiter 1abcdefg

6from starlette.concurrency import iterate_in_threadpool as iterate_in_threadpool # noqa 1abcdefg

7from starlette.concurrency import run_in_threadpool as run_in_threadpool # noqa 1abcdefg

8from starlette.concurrency import ( # noqa 1abcdefg

9 run_until_first_complete as run_until_first_complete, 

10) 

11 

12_T = TypeVar("_T") 1abcdefg

13 

14 

15@asynccontextmanager 1abcdefg

16async def contextmanager_in_threadpool( 1abcdefg

17 cm: ContextManager[_T], 

18) -> AsyncGenerator[_T, None]: 

19 # blocking __exit__ from running waiting on a free thread 

20 # can create race conditions/deadlocks if the context manager itself 

21 # has its own internal pool (e.g. a database connection pool) 

22 # to avoid this we let __exit__ run without a capacity limit 

23 # since we're creating a new limiter for each call, any non-zero limit 

24 # works (1 is arbitrary) 

25 exit_limiter = CapacityLimiter(1) 2@b[b]b(bv w x y ^b_b`b{bz |bA B C }bD E F ~bacbcccdcecfcgchcicjckclcmcncG ocH )bZbpcI 0bqcJ K L rch i sctcuc1bM N O P vcwcxcycQ zcR S T AcU V W BcCcDcEcFcGcHcIcJcKcLcMcNcOcPcX QcY 2b3bRcZ 4bSc0 1 2 Tcj k UcVcWc*b3 4 5 6 XcYcZc0c7 1c8 9 ! 2c# $ % 3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c' +c( +b5b,c) 6b-c* + , .cl m /c:c;c,b- . / : =c?c@c[c; ]c= ? @ ^c[ ] ^ _c`c{c|c}c~cadbdcdddedfdgdhdid_ jd` -b7bkd{ 8bld| } ~ mdn o ndodpd.babbbcbdbqdrdsdtdebudfbgbhbvdibjbkbwdxdydzdAdBdCdDdEdFdGdHdIdJdKdlbLdmb/b9bMdnb!bNdobpbqbOdp q PdQdRd:brbsbtbubSdTdUdVdvbWdwbxbybXdzbAbBbYdZd0d1d2d3d4d5d6d7d8d9d!d#d$dCb%dDb;b#b'dEb$b(dFbGbHb)dr s *d+d,d=bIbJbKbLb-d.d/d:dMb;dNbObPb=dQbRbSb?d@d[d]d^d_d`d{d|d}d~daebecedeTbeeUb?b%bfeVb'bgeWbXbYbhet u

26 try: 2@b[b]b(bv w x y ^b_b`b{bz |bA B C }bD E F ~bacbcccdcecfcgchcicjckclcmcncG ocH )bZbpcI 0bqcJ K L rch i sctcuc1bM N O P vcwcxcycQ zcR S T AcU V W BcCcDcEcFcGcHcIcJcKcLcMcNcOcPcX QcY 2b3bRcZ 4bSc0 1 2 Tcj k UcVcWc*b3 4 5 6 XcYcZc0c7 1c8 9 ! 2c# $ % 3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c' +c( +b5b,c) 6b-c* + , .cl m /c:c;c,b- . / : =c?c@c[c; ]c= ? @ ^c[ ] ^ _c`c{c|c}c~cadbdcdddedfdgdhdid_ jd` -b7bkd{ 8bld| } ~ mdn o ndodpd.babbbcbdbqdrdsdtdebudfbgbhbvdibjbkbwdxdydzdAdBdCdDdEdFdGdHdIdJdKdlbLdmb/b9bMdnb!bNdobpbqbOdp q PdQdRd:brbsbtbubSdTdUdVdvbWdwbxbybXdzbAbBbYdZd0d1d2d3d4d5d6d7d8d9d!d#d$dCb%dDb;b#b'dEb$b(dFbGbHb)dr s *d+d,d=bIbJbKbLb-d.d/d:dMb;dNbObPb=dQbRbSb?d@d[d]d^d_d`d{d|d}d~daebecedeTbeeUb?b%bfeVb'bgeWbXbYbhet u

27 yield await run_in_threadpool(cm.__enter__) 2@b[b]b(bv w x y ^b_b`b{bz |bA B C }bD E F ~bacbcccdcecfcgchcicjckclcmcncG ocH )bZbpcI 0bqcJ K L rch i sctcuc1bM N O P vcwcxcycQ zcR S T AcU V W BcCcDcEcFcGcHcIcJcKcLcMcNcOcPcX QcY 2b3bRcZ 4bSc0 1 2 Tcj k UcVcWc*b3 4 5 6 XcYcZc0c7 1c8 9 ! 2c# $ % 3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c' +c( +b5b,c) 6b-c* + , .cl m /c:c;c,b- . / : =c?c@c[c; ]c= ? @ ^c[ ] ^ _c`c{c|c}c~cadbdcdddedfdgdhdid_ jd` -b7bkd{ 8bld| } ~ mdn o ndodpd.babbbcbdbqdrdsdtdebudfbgbhbvdibjbkbwdxdydzdAdBdCdDdEdFdGdHdIdJdKdlbLdmb/b9bMdnb!bNdobpbqbOdp q PdQdRd:brbsbtbubSdTdUdVdvbWdwbxbybXdzbAbBbYdZd0d1d2d3d4d5d6d7d8d9d!d#d$dCb%dDb;b#b'dEb$b(dFbGbHb)dr s *d+d,d=bIbJbKbLb-d.d/d:dMb;dNbObPb=dQbRbSb?d@d[d]d^d_d`d{d|d}d~daebecedeTbeeUb?b%bfeVb'bgeWbXbYbhet u

28 except Exception as e: 2(bv w x y z A B C D E F G H )bZbI 0bJ K L h i 1bM N O P Q R S T U V W X Y 2b3bZ 4b0 1 2 j k *b3 4 5 6 7 8 9 ! # $ % ' ( +b5b) 6b* + , l m ,b- . / : ; = ? @ [ ] ^ _ ` -b7b{ 8b| } ~ n o .babbbcbdbebfbgbhbibjbkblbmb/b9bnb!bobpbqbp q :brbsbtbubvbwbxbybzbAbBbCbDb;b#bEb$bFbGbHbr s =bIbJbKbLbMbNbObPbQbRbSbTbUb?b%bVb'bWbXbYbt u

29 ok = bool( 2(bv w x y z A B C D E F G H )bZbI 0bJ K L h i 1bM N O P Q R S T U V W X Y 2b3bZ 4b0 1 2 j k *b3 4 5 6 7 8 9 ! # $ % ' ( +b5b) 6b* + , l m ,b- . / : ; = ? @ [ ] ^ _ ` -b7b{ 8b| } ~ n o .babbbcbdbebfbgbhbibjbkblbmb/b9bnb!bobpbqbp q :brbsbtbubvbwbxbybzbAbBbCbDb;b#bEb$bFbGbHbr s =bIbJbKbLbMbNbObPbQbRbSbTbUb?b%bVb'bWbXbYbt u

30 await anyio.to_thread.run_sync( 

31 cm.__exit__, type(e), e, e.__traceback__, limiter=exit_limiter 

32 ) 

33 ) 

34 if not ok: 2v w x y z A B C D E F G H ZbI 0bJ K L h i M N O P Q R S T U V W X Y 3bZ 4b0 1 2 j k 3 4 5 6 7 8 9 ! # $ % ' ( 5b) 6b* + , l m - . / : ; = ? @ [ ] ^ _ ` 7b{ 8b| } ~ n o abbbcbdbebfbgbhbibjbkblbmb9bnb!bobpbqbp q rbsbtbubvbwbxbybzbAbBbCbDb#bEb$bFbGbHbr s IbJbKbLbMbNbObPbQbRbSbTbUb%bVb'bWbXbYbt u

35 raise e 2v w x y z A B C D E F G H I J K L h i 1bM N O P Q R S T U V W X Y 2bZ 0 1 2 j k 3 4 5 6 7 8 9 ! # $ % ' ( ) * + , l m - . / : ; = ? @ [ ] ^ _ ` { | } ~ n o abbbcbdbebfbgbhbibjbkblbmbnbobpbqbp q rbsbtbubvbwbxbybzbAbBbCbDbEbFbGbHbr s IbJbKbLbMbNbObPbQbRbSbTbUbVbWbXbYbt u

36 else: 

37 await anyio.to_thread.run_sync( 2@b[b]b^b_b`b{b|b}b~bacbcccdcecfcgchcicjckclcmcncocpcqcrch i sctcucvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcLcMcNcOcPcQcRcScTcj k UcVcWcXcYcZc0c1c2c3c4c5c6c7c8c9c!c#c$c%c'c(c)c*c+c,c-c.cl m /c:c;c=c?c@c[c]c^c_c`c{c|c}c~cadbdcdddedfdgdhdidjdkdldmdn o ndodpdqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdp q PdQdRdSdTdUdVdWdXdYdZd0d1d2d3d4d5d6d7d8d9d!d#d$d%d'd(d)dr s *d+d,d-d.d/d:d;d=d?d@d[d]d^d_d`d{d|d}d~daebecedeeefegehet u

38 cm.__exit__, None, None, None, limiter=exit_limiter 

39 )