Coverage for src/fastapi_cli/config.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.16.2, created at 2026-11-11 09:18 +0000

1import logging 1fghijklmnopqrs

2from pathlib import Path 1fghijklmnopqrs

3from typing import Any 1fghijklmnopqrs

4 

5from pydantic import BaseModel, StrictStr 1fghijklmnopqrs

6 

7logger = logging.getLogger(__name__) 1fghijklmnopqrs

8 

9 

10class FastAPIConfig(BaseModel): 1fghijklmnopqrs

11 entrypoint: StrictStr | None = None 1fghijklmnopqrs

12 from_pyproject: bool = False 1fghijklmnopqrs

13 

14 @classmethod 1fghijklmnopqrs

15 def _read_pyproject_toml(cls) -> dict[str, Any]: 1fghijklmnopqrs

16 """Read FastAPI configuration from pyproject.toml in current directory.""" 

17 pyproject_path = Path.cwd() / "pyproject.toml" 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ a b c d e SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} t u v w x 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}baby z A B C ~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbD E F G H vcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebI J K L M RcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgbN O P Q R %c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cibS T U V W }c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbX Y Z 0 1 udvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmb2 3 4 5 6 QdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob7 8 9 ! # $d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb$ % ' ( ) |d}d~daebecedeeefegeheierbjekelemeneoepeqeresesb* + , - . teuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeub/ : ; = ? PeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb@ [ ] ^ _ #e

18 

19 if not pyproject_path.exists(): 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ a b c d e SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} t u v w x 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}baby z A B C ~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbD E F G H vcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebI J K L M RcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgbN O P Q R %c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cibS T U V W }c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbX Y Z 0 1 udvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmb2 3 4 5 6 QdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob7 8 9 ! # $d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb$ % ' ( ) |d}d~daebecedeeefegeheierbjekelemeneoepeqeresesb* + , - . teuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeub/ : ; = ? PeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb@ [ ] ^ _ #e

20 return {} 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}bab~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbvcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebRcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgb%c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cib}c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbudvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmbQdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob$d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb|d}d~daebecedeeefegeheierbjekelemeneoepeqeresesbteuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeubPeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb#e

21 

22 try: 1abcdetuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_

23 import tomllib # type: ignore[import-not-found, unused-ignore] # ty: ignore[unresolved-import] 1abcdetuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_

24 except ImportError: 1abcde

25 try: 1abcde

26 import tomli as tomllib # type: ignore[no-redef, import-not-found, unused-ignore] 1abcde

27 except ImportError: # pragma: no cover 

28 logger.debug("tomli not available, skipping pyproject.toml") 

29 return {} 

30 

31 with open(pyproject_path, "rb") as f: 1abcdetuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_

32 data = tomllib.load(f) 1abcdetuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_

33 

34 return data.get("tool", {}).get("fastapi", {}) # type: ignore[no-any-return] 1abcdetuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%'()*+,-./:;=?@[]^_

35 

36 @classmethod 1fghijklmnopqrs

37 def resolve(cls, entrypoint: str | None = None) -> "FastAPIConfig": 1fghijklmnopqrs

38 config = cls._read_pyproject_toml() 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ a b c d e SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} t u v w x 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}baby z A B C ~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbD E F G H vcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebI J K L M RcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgbN O P Q R %c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cibS T U V W }c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbX Y Z 0 1 udvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmb2 3 4 5 6 QdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob7 8 9 ! # $d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb$ % ' ( ) |d}d~daebecedeeefegeheierbjekelemeneoepeqeresesb* + , - . teuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeub/ : ; = ? PeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb@ [ ] ^ _ #e

39 

40 if entrypoint is not None: 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ a b c d e SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} t u v w x 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}baby z A B C ~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbD E F G H vcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebI J K L M RcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgbN O P Q R %c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cibS T U V W }c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbX Y Z 0 1 udvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmb2 3 4 5 6 QdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob7 8 9 ! # $d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb$ % ' ( ) |d}d~daebecedeeefegeheierbjekelemeneoepeqeresesb* + , - . teuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeub/ : ; = ? PeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb@ [ ] ^ _ #e

41 config["entrypoint"] = entrypoint 2` { | } ~ abbbcbdbebfbgbhbibjbkblbmbnbobpbqbrbsbtbubvbwb

42 

43 config["from_pyproject"] = ("entrypoint" in config) and (entrypoint is None) 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ a b c d e SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} t u v w x 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}baby z A B C ~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbD E F G H vcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebI J K L M RcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgbN O P Q R %c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cibS T U V W }c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbX Y Z 0 1 udvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmb2 3 4 5 6 QdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob7 8 9 ! # $d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb$ % ' ( ) |d}d~daebecedeeefegeheierbjekelemeneoepeqeresesb* + , - . teuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeub/ : ; = ? PeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb@ [ ] ^ _ #e

44 

45 return cls.model_validate(config) 2xbybzbAbBbCbDbEbFbGbHb` IbJbKbLbMbNbObPbQbRb{ a b c d e SbTbUbVbWbXbYbZb0b1b2b3b| 4b5b6b7b8b9b!b#b$b%b} t u v w x 'b(b)b*b+b,b-b.b/b:b;b=b~ ?b@b[b]b^b_b`b{b|b}baby z A B C ~bacbcccdcecfcgchcicjckcbblcmcncocpcqcrcsctcuccbD E F G H vcwcxcyczcAcBcCcDcEcFcGcdbHcIcJcKcLcMcNcOcPcQcebI J K L M RcScTcUcVcWcXcYcZc0c1c2cfb3c4c5c6c7c8c9c!c#c$cgbN O P Q R %c'c(c)c*c+c,c-c.c/c:c;chb=c?c@c[c]c^c_c`c{c|cibS T U V W }c~cadbdcdddedfdgdhdidjdjbkdldmdndodpdqdrdsdtdkbX Y Z 0 1 udvdwdxdydzdAdBdCdDdEdFdlbGdHdIdJdKdLdMdNdOdPdmb2 3 4 5 6 QdRdSdTdUdVdWdXdYdZd0d1dnb2d3d4d5d6d7d8d9d!d#dob7 8 9 ! # $d%d'd(d)d*d+d,d-d.d/d:dpb;d=d?d@d[d]d^d_d`d{dqb$ % ' ( ) |d}d~daebecedeeefegeheierbjekelemeneoepeqeresesb* + , - . teuevewexeyezeAeBeCeDeEetbFeGeHeIeJeKeLeMeNeOeub/ : ; = ? PeQeReSeTeUeVeWeXeYeZe0evb1e2e3e4e5e6e7e8e9e!ewb@ [ ] ^ _ #e