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

136 statements  

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

1import logging 2ebfbgbhbibjbkblbmbnbobpbqbrb

2import os 2ebfbgbhbibjbkblbmbnbobpbqbrb

3from pathlib import Path 2ebfbgbhbibjbkblbmbnbobpbqbrb

4from typing import Annotated, Any 2ebfbgbhbibjbkblbmbnbobpbqbrb

5 

6import typer 2ebfbgbhbibjbkblbmbnbobpbqbrb

7from pydantic import ValidationError 2ebfbgbhbibjbkblbmbnbobpbqbrb

8from rich import print 2ebfbgbhbibjbkblbmbnbobpbqbrb

9from rich.syntax import Syntax 2ebfbgbhbibjbkblbmbnbobpbqbrb

10from rich.tree import Tree 2ebfbgbhbibjbkblbmbnbobpbqbrb

11 

12from fastapi_cli.config import FastAPIConfig 2ebfbgbhbibjbkblbmbnbobpbqbrb

13from fastapi_cli.discover import ( 2ebfbgbhbibjbkblbmbnbobpbqbrb

14 AppConfigSource, 

15 ModuleConfigSource, 

16 get_import_data, 

17 get_import_data_from_import_string, 

18) 

19from fastapi_cli.exceptions import FastAPICLIException 2ebfbgbhbibjbkblbmbnbobpbqbrb

20 

21from . import __version__ 2ebfbgbhbibjbkblbmbnbobpbqbrb

22from .logging import setup_logging 2ebfbgbhbibjbkblbmbnbobpbqbrb

23from .utils.cli import ( 2ebfbgbhbibjbkblbmbnbobpbqbrb

24 get_rich_toolkit, 

25 get_uvicorn_log_config, 

26 should_use_rich_logs, 

27) 

28 

29app = typer.Typer( 2ebfbgbhbibjbkblbmbnbobpbqbrb

30 rich_markup_mode="rich", context_settings={"help_option_names": ["-h", "--help"]} 

31) 

32 

33logger = logging.getLogger(__name__) 2ebfbgbhbibjbkblbmbnbobpbqbrb

34 

35 

36SOURCE_DESCRIPTIONS: dict[ModuleConfigSource | AppConfigSource, str] = { 2ebfbgbhbibjbkblbmbnbobpbqbrb

37 "entrypoint-option": "[blue]--entrypoint[/] CLI option", 

38 "entrypoint-pyproject": "[blue]entrypoint[/] in [blue]pyproject.toml[/]", 

39 "path-argument": "[blue]path[/] CLI argument", 

40 "app-option": "[blue]--app[/] CLI option", 

41 "auto-discovery": "auto-discovery", 

42} 

43 

44 

45try: 2ebfbgbhbibjbkblbmbnbobpbqbrb

46 import uvicorn 2ebfbgbhbibjbkblbmbnbobpbqbrb

47except ImportError: # pragma: no cover 

48 uvicorn = None # type: ignore[assignment] 

49 

50 

51try: 2ebfbgbhbibjbkblbmbnbobpbqbrb

52 from fastapi_cloud_cli.cli import ( 2ebfbgbhbibjbkblbmbnbobpbqbrb

53 app as fastapi_cloud_cli, 

54 ) 

55 

56 app.add_typer(fastapi_cloud_cli) 2ebfbgbhbibjbkblbmbnbobpbqbrb

57except ImportError: # pragma: no cover 

58 pass 

59 

60 

61try: 2ebfbgbhbibjbkblbmbnbobpbqbrb

62 from fastapi_new.cli import ( # type: ignore[import-not-found] # ty: ignore[unresolved-import] 2ebfbgbhbibjbkblbmbnbobpbqbrb

63 app as fastapi_new_cli, 

64 ) 

65 

66 app.add_typer(fastapi_new_cli) # pragma: no cover 

67except ImportError: # pragma: no cover 2ebfbgbhbibjbkblbmbnbobpbqbrb

68 pass 2ebfbgbhbibjbkblbmbnbobpbqbrb

69 

70 

71def version_callback(value: bool) -> None: 2ebfbgbQ hbibR S jbkblbT mbnbU V obpbW qbrbX Y

72 if value: 2sbtbubvbwbrfC xbybzba o Z $e%eAb0 ~cadbdcdddYesfedfdBbdfCb1 wexeDbieEbFbGbHbIbtfD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeufldmdNbefOb4 yezePbjeQ QbRbSbTbvfE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0ewfsdtdYbffZb7 AeBe0bkeR 1b2b3b4bxfF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1eyfzdAd9bgf!b! CeDe#bleS $b%b'b(bzfG )b*b+be s # -e.e,b$ BdCdDdEdFd2eAfGdHd-bhf.b% EeFe/bme:b;b=b?b@bBfH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eCfNdOd`bif{b) GeHe|bne}b~bacbcccDfI dcecfcg u * ;e=egc+ PdQdRdSdTd4eEfUdVdhcjfic, IeJejcoeT kclcmcncFfJ ocpcqch v - ?e@erc. WdXdYdZd0d5eGf1d2dsckftc/ KeLeucpeU vcwcxcycHfK zcAcBci w : [e]eCc; 3d4d5d6d7d6eIf8d9dDclfEc= MeNeFcqeV GcHcIcJcJfL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7eKf(d)dOcmfPc[ OePeQcreRcScTcUcVcLfM WcXcYck y ] `e{eZc^ *d+d,d-d.d8eMf/d:d0cnf1c_ QeRe2cseW 3c4c5c6cNfN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9eOf]d^d#cof$c| SeTe%cteX 'c(c)c*cPfO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!eQf~dae/cpf:cabUeVe;cueY =c?c@c[cRfP ]c^c_cn B bbbfcf`ccbbecedeeefe#eSfgehe{cqf|cdbWeXe}cve

73 print(f"FastAPI CLI version: [green]{__version__}[/green]") 2dfefffgfhfifjfkflfmfnfofpfqf

74 try: 2dfefffgfhfifjfkflfmfnfofpfqf

75 from fastapi_cloud_cli import ( 2dfefffgfhfifjfkflfmfnfofpfqf

76 __version__ as cloud_cli_version, 

77 ) 

78 

79 print(f"FastAPI Cloud CLI version: [green]{cloud_cli_version}[/green]") 2dfefffgfhfifjfkflfmfnfofpfqf

80 except ImportError: # pragma: no cover 

81 pass 

82 

83 raise typer.Exit() 2dfefffgfhfifjfkflfmfnfofpfqf

84 

85 

86@app.callback() 2ebfbgbhbibjbkblbmbnbobpbqbrb

87def callback( 2ebfbgbQ hbibR S jbkblbT mbnbU V obpbW qbrbX Y

88 version: Annotated[ 

89 bool | None, 

90 typer.Option( 

91 "--version", help="Show the version and exit.", callback=version_callback 

92 ), 

93 ] = None, 

94 verbose: bool = typer.Option(False, help="Enable verbose output"), 

95) -> None: 

96 """ 

97 FastAPI CLI - The [bold]fastapi[/bold] command line app. 😎 

98 

99 Manage your [bold]FastAPI[/bold] projects, run your FastAPI apps, and more. 

100 

101 Read more in the docs: [link=https://fastapi.tiangolo.com/fastapi-cli/]https://fastapi.tiangolo.com/fastapi-cli/[/link]. 

102 """ 

103 

104 log_level = logging.DEBUG if verbose else logging.INFO 2sbtbubvbwbrfC xbybzba o Z $e%eAb0 ~cadbdcdddYesfedfdBbCb1 wexeDbieEbFbGbHbIbtfD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeufldmdNbOb4 yezePbjeQ QbRbSbTbvfE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0ewfsdtdYbZb7 AeBe0bkeR 1b2b3b4bxfF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1eyfzdAd9b!b! CeDe#bleS $b%b'b(bzfG )b*b+be s # -e.e,b$ BdCdDdEdFd2eAfGdHd-b.b% EeFe/bme:b;b=b?b@bBfH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eCfNdOd`b{b) GeHe|bne}b~bacbcccDfI dcecfcg u * ;e=egc+ PdQdRdSdTd4eEfUdVdhcic, IeJejcoeT kclcmcncFfJ ocpcqch v - ?e@erc. WdXdYdZd0d5eGf1d2dsctc/ KeLeucpeU vcwcxcycHfK zcAcBci w : [e]eCc; 3d4d5d6d7d6eIf8d9dDcEc= MeNeFcqeV GcHcIcJcJfL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7eKf(d)dOcPc[ OePeQcreRcScTcUcVcLfM WcXcYck y ] `e{eZc^ *d+d,d-d.d8eMf/d:d0c1c_ QeRe2cseW 3c4c5c6cNfN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9eOf]d^d#c$c| SeTe%cteX 'c(c)c*cPfO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!eQf~dae/c:cabUeVe;cueY =c?c@c[cRfP ]c^c_cn B bbbfcf`ccbbecedeeefe#eSfgehe{c|cdbWeXe}cve

105 

106 setup_logging(level=log_level) 2sbtbubvbwbrfC xbybzba o Z $e%eAb0 ~cadbdcdddYesfedfdBbCb1 wexeDbieEbFbGbHbIbtfD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeufldmdNbOb4 yezePbjeQ QbRbSbTbvfE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0ewfsdtdYbZb7 AeBe0bkeR 1b2b3b4bxfF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1eyfzdAd9b!b! CeDe#bleS $b%b'b(bzfG )b*b+be s # -e.e,b$ BdCdDdEdFd2eAfGdHd-b.b% EeFe/bme:b;b=b?b@bBfH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eCfNdOd`b{b) GeHe|bne}b~bacbcccDfI dcecfcg u * ;e=egc+ PdQdRdSdTd4eEfUdVdhcic, IeJejcoeT kclcmcncFfJ ocpcqch v - ?e@erc. WdXdYdZd0d5eGf1d2dsctc/ KeLeucpeU vcwcxcycHfK zcAcBci w : [e]eCc; 3d4d5d6d7d6eIf8d9dDcEc= MeNeFcqeV GcHcIcJcJfL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7eKf(d)dOcPc[ OePeQcreRcScTcUcVcLfM WcXcYck y ] `e{eZc^ *d+d,d-d.d8eMf/d:d0c1c_ QeRe2cseW 3c4c5c6cNfN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9eOf]d^d#c$c| SeTe%cteX 'c(c)c*cPfO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!eQf~dae/c:cabUeVe;cueY =c?c@c[cRfP ]c^c_cn B bbbfcf`ccbbecedeeefe#eSfgehe{c|cdbWeXe}cve

107 

108 

109def _get_module_tree(module_paths: list[Path]) -> Tree: 2ebfbgbhbibjbkblbmbnbobpbqbrb

110 root = module_paths[0] 1aobpcqdresftguhviwjxkylzmAnB

111 name = f"🐍 {root.name}" if root.is_file() else f"📁 {root.name}" 1aobpcqdresftguhviwjxkylzmAnB

112 

113 root_tree = Tree(name) 1aobpcqdresftguhviwjxkylzmAnB

114 

115 if root.is_dir(): 1aobpcqdresftguhviwjxkylzmAnB

116 root_tree.add("[dim]🐍 __init__.py[/dim]") 1abcdefghijklmn

117 

118 tree = root_tree 1aobpcqdresftguhviwjxkylzmAnB

119 for sub_path in module_paths[1:]: 1aobpcqdresftguhviwjxkylzmAnB

120 sub_name = ( 1abcdefghijklmn

121 f"🐍 {sub_path.name}" if sub_path.is_file() else f"📁 {sub_path.name}" 

122 ) 

123 tree = tree.add(sub_name) 1abcdefghijklmn

124 if sub_path.is_dir(): 1abcdefghijklmn

125 tree.add("[dim]🐍 __init__.py[/dim]") 1abcdefghijklmn

126 

127 return root_tree 1aobpcqdresftguhviwjxkylzmAnB

128 

129 

130def _run( 2ebfbgbhbibjbkblbmbnbobpbqbrb

131 path: Path | None = None, 

132 *, 

133 host: str = "127.0.0.1", 

134 port: int = 8000, 

135 reload: bool = True, 

136 reload_dirs: list[Path] | None = None, 

137 workers: int | None = None, 

138 root_path: str = "", 

139 command: str, 

140 app: str | None = None, 

141 entrypoint: str | None = None, 

142 proxy_headers: bool = False, 

143 forwarded_allow_ips: str | None = None, 

144 public_url: str | None = None, 

145 verbose: bool = False, 

146) -> None: 

147 with get_rich_toolkit() as toolkit: 2sbtbubvbwbC xbybzba o Z $e%eAb0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # -e.e,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * ;e=egc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - ?e@erc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : [e]eCc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] `e{eZc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bbbfcf`ccbbecedeeefe#egehe{c|cdbWeXe}cve

148 server_type = "development" if command == "dev" else "production" 2sbtbubvbwbC xbybzba o Z $e%eAb0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # -e.e,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * ;e=egc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - ?e@erc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : [e]eCc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] `e{eZc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bbbfcf`ccbbecedeeefe#egehe{c|cdbWeXe}cve

149 

150 toolkit.print(f"Starting FastAPI in {server_type} mode", emoji="⚡️") 2sbtbubvbwbC xbybzba o Z $e%eAb0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # -e.e,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * ;e=egc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - ?e@erc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : [e]eCc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] `e{eZc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bbbfcf`ccbbecedeeefe#egehe{c|cdbWeXe}cve

151 

152 if verbose: 2sbtbubvbwbC xbybzba o Z $e%eAb0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # -e.e,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * ;e=egc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - ?e@erc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : [e]eCc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] `e{eZc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bbbfcf`ccbbecedeeefe#egehe{c|cdbWeXe}cve

153 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB

154 toolkit.print( 1aobpcqdresftguhviwjxkylzmAnB

155 "Searching for package file structure from directories with [blue]__init__.py[/blue] files", 

156 emoji="🔎", 

157 ) 

158 

159 if entrypoint and (path or app): 2sbtbubvbwbC xbybzba o Z $e%eAb0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # -e.e,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' /e:e_b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * ;e=egc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - ?e@erc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : [e]eCc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] `e{eZc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bbbfcf`ccbbecedeeefe#egehe{c|cdbWeXe}cve

160 toolkit.print_line() 2$e%e'e(e)e*e+e,e-e.e/e:e;e=e?e@e[e]e^e_e`e{e|e}e~eafbfcf

161 toolkit.print( 2$e%e'e(e)e*e+e,e-e.e/e:e;e=e?e@e[e]e^e_e`e{e|e}e~eafbfcf

162 "[error]Cannot use --entrypoint together with path or --app arguments" 

163 ) 

164 raise typer.Exit(code=1) 2$e%e'e(e)e*e+e,e-e.e/e:e;e=e?e@e[e]e^e_e`e{e|e}e~eafbfcf

165 

166 try: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefe#egehe{c|cdbWeXe}cve

167 config = FastAPIConfig.resolve(entrypoint=entrypoint) 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddYeedfdBbCb1 wexeDbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdZeldmdNbOb4 yezePbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrd0esdtdYbZb7 AeBe0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdyd1ezdAd9b!b! CeDe#bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFd2eGdHd-b.b% EeFe/bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMd3eNdOd`b{b) GeHe|bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTd4eUdVdhcic, IeJejcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d5e1d2dsctc/ KeLeucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d6e8d9dDcEc= MeNeFcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd7e(d)dOcPc[ OePeQcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d8e/d:d0c1c_ QeRe2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d9e]d^d#c$c| SeTe%cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d!e~dae/c:cabUeVe;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefe#egehe{c|cdbWeXe}cve

168 except ValidationError as e: 2xezeBeDeFeHeJeLeNePeReTeVeXe

169 toolkit.print_line() 2xezeBeDeFeHeJeLeNePeReTeVeXe

170 toolkit.print("[error]Invalid configuration in pyproject.toml:") 2xezeBeDeFeHeJeLeNePeReTeVeXe

171 toolkit.print_line() 2xezeBeDeFeHeJeLeNePeReTeVeXe

172 

173 for error in e.errors(): 2xezeBeDeFeHeJeLeNePeReTeVeXe

174 field = ".".join(str(loc) for loc in error["loc"]) 2xezeBeDeFeHeJeLeNePeReTeVeXe

175 toolkit.print(f" [red]•[/red] {field}: {error['msg']}") 2xezeBeDeFeHeJeLeNePeReTeVeXe

176 

177 raise typer.Exit(code=1) from None 2xezeBeDeFeHeJeLeNePeReTeVeXe

178 

179 try: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddYeedfdBbCb1 weDbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdZeldmdNbOb4 yePbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrd0esdtdYbZb7 Ae0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdyd1ezdAd9b!b! Ce#bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFd2eGdHd-b.b% Ee/bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMd3eNdOd`b{b) Ge|bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTd4eUdVdhcic, IejcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d5e1d2dsctc/ KeucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d6e8d9dDcEc= MeFcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd7e(d)dOcPc[ OeQcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d8e/d:d0c1c_ Qe2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d9e]d^d#c$c| Se%cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d!e~dae/c:cabUe;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefe#egehe{c|cdbWe}cve

180 # Resolve import data with priority: CLI path/app > config entrypoint > auto-discovery 

181 if path or app: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddYeedfdBbCb1 weDbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdZeldmdNbOb4 yePbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrd0esdtdYbZb7 Ae0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdyd1ezdAd9b!b! Ce#bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFd2eGdHd-b.b% Ee/bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMd3eNdOd`b{b) Ge|bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTd4eUdVdhcic, IejcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d5e1d2dsctc/ KeucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d6e8d9dDcEc= MeFcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd7e(d)dOcPc[ OeQcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d8e/d:d0c1c_ Qe2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d9e]d^d#c$c| Se%cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d!e~dae/c:cabUe;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefe#egehe{c|cdbWe}cve

182 import_data = get_import_data(path=path, app_name=app) 2sbtbubvbwbxbybzba Ab0 ~cadbdcdddYeedfdCbieEbFbGbHbIbJbKbLbb Mb3 gdhdidjdkdZeldmdObjeQ QbRbSbTbUbVbWbc Xb6 ndodpdqdrd0esdtdZbkeR 1b2b3b4b5b6b7bd 8b9 udvdwdxdyd1ezdAd!bleS $b%b'b(b)b*b+be ,b$ BdCdDdEdFd2eGdHd.bme:b;b=b?b@b[b]b^bf _b( IdJdKdLdMd3eNdOd{bne}b~bacbcccdcecfcg gc+ PdQdRdSdTd4eUdVdicoeT kclcmcncocpcqch rc. WdXdYdZd0d5e1d2dtcpeU vcwcxcyczcAcBci Cc; 3d4d5d6d7d6e8d9dEcqeV GcHcIcJcKcLcMcj Nc@ !d#d$d%d'd7e(d)dPcreRcScTcUcVcWcXcYck Zc^ *d+d,d-d.d8e/d:d1cseW 3c4c5c6c7c8c9cl !c{ ;d=d?d@d[d9e]d^d$cteX 'c(c)c*c+c,c-cm .c~ _d`d{d|d}d!e~dae:cueY =c?c@c[c]c^c_cn `ccbbecedeeefe#egehe|cve

183 elif config.entrypoint: 2C o Z Bb1 weDbD p 2 Nb4 yePbE q 5 Yb7 Ae0bF r 8 9b! Ce#bG s # -b% Ee/bH t ' `b) Ge|bI u * hc, IejcJ v - sc/ KeucK w : Dc= MeFcL x ? Oc[ OeQcM y ] 0c_ Qe2cN z ` #c| Se%cO A } /cabUe;cP B bb{cdbWe}c

184 import_data = get_import_data_from_import_string( 2Z Bb1 weDb2 Nb4 yePb5 Yb7 Ae0b8 9b! Ce#b# -b% Ee/b' `b) Ge|b* hc, Iejc- sc/ Keuc: Dc= MeFc? Oc[ OeQc] 0c_ Qe2c` #c| Se%c} /cabUe;cbb{cdbWe}c

185 config.entrypoint, config.from_pyproject 

186 ) 

187 else: 

188 import_data = get_import_data() 1CoDpEqFrGsHtIuJvKwLxMyNzOAPB

189 except FastAPICLIException as e: 2YeweZeye0eAe1eCe2eEe3eGe4eIe5eKe6eMe7eOe8eQe9eSe!eUe#eWe

190 toolkit.print_line() 2YeweZeye0eAe1eCe2eEe3eGe4eIe5eKe6eMe7eOe8eQe9eSe!eUe#eWe

191 toolkit.print(f"[error]{e}") 2YeweZeye0eAe1eCe2eEe3eGe4eIe5eKe6eMe7eOe8eQe9eSe!eUe#eWe

192 raise typer.Exit(code=1) from None 2YeweZeye0eAe1eCe2eEe3eGe4eIe5eKe6eMe7eOe8eQe9eSe!eUe#eWe

193 

194 logger.debug(f"Importing from {import_data.module_data.extra_sys_path}") 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

195 logger.debug(f"Importing module {import_data.module_data.module_import_str}") 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

196 

197 module_data = import_data.module_data 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

198 import_string = import_data.import_string 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

199 is_auto_discovery = import_data.module_config_source == "auto-discovery" 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

200 

201 if verbose: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

202 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB

203 toolkit.print(f"Importing from {module_data.extra_sys_path}", emoji="📂") 1aobpcqdresftguhviwjxkylzmAnB

204 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB

205 

206 if module_data.module_paths: 1aobpcqdresftguhviwjxkylzmAnB

207 root_tree = _get_module_tree(module_data.module_paths) 1aobpcqdresftguhviwjxkylzmAnB

208 

209 toolkit.print(root_tree) 1aobpcqdresftguhviwjxkylzmAnB

210 

211 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB

212 

213 toolkit.print( 1aobpcqdresftguhviwjxkylzmAnB

214 "Importing the FastAPI app object from the module with the following code:", 

215 ) 

216 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB

217 toolkit.print( 1aobpcqdresftguhviwjxkylzmAnB

218 f"[blue]from [bold]{module_data.module_import_str}[/bold] import [bold]{import_data.app_name}[/bold]", 

219 ) 

220 

221 # Outside --verbose, fold the resolution source into the import string 

222 # line and point newcomers at --verbose for the full explanation 

223 if is_auto_discovery and not verbose: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

224 app_note = " [dim](auto-discovered, use --verbose to learn more)[/]" 1CDEFGHIJKLMNOP

225 else: 

226 app_note = "" 2sbtbubvbwbxbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbJbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbUbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4b5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(b)b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@b[b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccdcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcyczcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcKcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcWcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6c7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*c+c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[c]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

227 

228 toolkit.print_line() 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

229 toolkit.print( 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

230 f"Using import string: [blue]{import_string}[/]{app_note}", emoji="🐍" 

231 ) 

232 

233 if verbose: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

234 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB

235 mod_source_desc = SOURCE_DESCRIPTIONS[import_data.module_config_source] 1aobpcqdresftguhviwjxkylzmAnB

236 app_source_desc = SOURCE_DESCRIPTIONS[import_data.app_name_config_source] 1aobpcqdresftguhviwjxkylzmAnB

237 toolkit.print("Configuration sources:", emoji="📋") 1aobpcqdresftguhviwjxkylzmAnB

238 if mod_source_desc == app_source_desc: 1aobpcqdresftguhviwjxkylzmAnB

239 toolkit.print(f"• Import string: {mod_source_desc}") 1opqrstuvwxyzAB

240 else: 

241 toolkit.print(f"• Module: {mod_source_desc}") 1abcdefghijklmn

242 toolkit.print(f"• App name: {app_source_desc}") 1abcdefghijklmn

243 

244 # Nudge to pin the entrypoint whenever it was auto-discovered, so it's 

245 # explicit next time — shown in the default output, not just --verbose 

246 if is_auto_discovery: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

247 toolkit.print_line() 1CoDpEqFrGsHtIuJvKwLxMyNzOAPB

248 toolkit.print( 1CoDpEqFrGsHtIuJvKwLxMyNzOAPB

249 "You can configure an entrypoint in [blue]pyproject.toml[/] for this app with:", 

250 emoji="💡", 

251 ) 

252 toolkit.print_line() 1CoDpEqFrGsHtIuJvKwLxMyNzOAPB

253 toolkit.print( 1CoDpEqFrGsHtIuJvKwLxMyNzOAPB

254 Syntax( 

255 ( 

256 "[tool.fastapi]\n" 

257 f'entrypoint = "{import_data.module_data.module_import_str}:{import_data.app_name}"' 

258 ), 

259 "toml", 

260 theme="ansi_light", 

261 ), 

262 ) 

263 

264 url = public_url.rstrip("/") if public_url else f"http://{host}:{port}" 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

265 url_docs = f"{url}/docs" 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

266 

267 toolkit.print_line() 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

268 toolkit.print(f"Server started at [link={url}]{url}[/]", emoji="🌐") 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

269 toolkit.print(f"Documentation at [link={url_docs}]{url_docs}[/]") 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

270 

271 if not uvicorn: 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbieEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbjeQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bkeR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bleS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /bme:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |bne}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcoeT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucpeU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcqeV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcreRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cseW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cteX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cueY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}cve

272 raise FastAPICLIException( 2iejekelemeneoepeqereseteueve

273 "Could not import Uvicorn, try running 'pip install uvicorn'" 

274 ) from None 

275 

276 toolkit.print_line() 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /b:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |b}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}c

277 toolkit.print("Logs:", bullet=False) 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /b:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |b}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}c

278 toolkit.print_line() 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /b:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |b}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}c

279 

280 extra_uvicorn_kwargs: dict[str, Any] = ( 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /b:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |b}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}c

281 {"log_config": get_uvicorn_log_config()} if should_use_rich_logs() else {} 

282 ) 

283 

284 uvicorn.run( 2sbtbubvbwbC xbybzba o Z Ab0 ~cadbdcdddedfdBbCb1 DbEbFbGbHbIbD JbKbLbb p 2 Mb3 gdhdidjdkdldmdNbOb4 PbQ QbRbSbTbE UbVbWbc q 5 Xb6 ndodpdqdrdsdtdYbZb7 0bR 1b2b3b4bF 5b6b7bd r 8 8b9 udvdwdxdydzdAd9b!b! #bS $b%b'b(bG )b*b+be s # ,b$ BdCdDdEdFdGdHd-b.b% /b:b;b=b?b@bH [b]b^bf t ' _b( IdJdKdLdMdNdOd`b{b) |b}b~bacbcccI dcecfcg u * gc+ PdQdRdSdTdUdVdhcic, jcT kclcmcncJ ocpcqch v - rc. WdXdYdZd0d1d2dsctc/ ucU vcwcxcycK zcAcBci w : Cc; 3d4d5d6d7d8d9dDcEc= FcV GcHcIcJcL KcLcMcj x ? Nc@ !d#d$d%d'd(d)dOcPc[ QcRcScTcUcVcM WcXcYck y ] Zc^ *d+d,d-d.d/d:d0c1c_ 2cW 3c4c5c6cN 7c8c9cl z ` !c{ ;d=d?d@d[d]d^d#c$c| %cX 'c(c)c*cO +c,c-cm A } .c~ _d`d{d|d}d~dae/c:cab;cY =c?c@c[cP ]c^c_cn B bb`ccbbecedeeefegehe{c|cdb}c

285 app=import_string, 

286 host=host, 

287 port=port, 

288 reload=reload, 

289 reload_dirs=( 

290 [str(directory.resolve()) for directory in reload_dirs] 

291 if reload_dirs 

292 else None 

293 ), 

294 workers=workers, 

295 root_path=root_path, 

296 proxy_headers=proxy_headers, 

297 forwarded_allow_ips=forwarded_allow_ips, 

298 **extra_uvicorn_kwargs, 

299 ) 

300 

301 

302@app.command() 2ebfbgbhbibjbkblbmbnbobpbqbrb

303def dev( 2ebfbgbQ hbibR S jbkblbT mbnbU V obpbW qbrbX Y

304 path: Annotated[ 

305 Path | None, 

306 typer.Argument( 

307 help="A path to a Python file or package directory (with [blue]__init__.py[/blue] files) containing a [bold]FastAPI[/bold] app. If not provided, a default set of paths will be tried." 

308 ), 

309 ] = None, 

310 *, 

311 host: Annotated[ 

312 str, 

313 typer.Option( 

314 help="The host to serve on. For local development in localhost use [blue]127.0.0.1[/blue]. To enable public access, e.g. in a container, use all the IP addresses available with [blue]0.0.0.0[/blue]." 

315 ), 

316 ] = "127.0.0.1", 

317 port: Annotated[ 

318 int, 

319 typer.Option( 

320 help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app.", 

321 envvar="PORT", 

322 ), 

323 ] = 8000, 

324 reload: Annotated[ 

325 bool, 

326 typer.Option( 

327 help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development." 

328 ), 

329 ] = True, 

330 reload_dir: Annotated[ 

331 list[Path] | None, 

332 typer.Option( 

333 help="Set reload directories explicitly, instead of using the current working directory." 

334 ), 

335 ] = None, 

336 root_path: Annotated[ 

337 str, 

338 typer.Option( 

339 help="The root path is used to tell your app that it is being served to the outside world with some [bold]path prefix[/bold] set up in some termination proxy or similar." 

340 ), 

341 ] = "", 

342 app: Annotated[ 

343 str | None, 

344 typer.Option( 

345 help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically." 

346 ), 

347 ] = None, 

348 entrypoint: Annotated[ 

349 str | None, 

350 typer.Option( 

351 "--entrypoint", 

352 "-e", 

353 help="The FastAPI app import string in the format 'some.importable_module:app_name'.", 

354 ), 

355 ] = None, 

356 proxy_headers: Annotated[ 

357 bool, 

358 typer.Option( 

359 help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info." 

360 ), 

361 ] = True, 

362 forwarded_allow_ips: Annotated[ 

363 str | None, 

364 typer.Option( 

365 help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything." 

366 ), 

367 ] = None, 

368 verbose: Annotated[ 

369 bool, 

370 typer.Option( 

371 "--verbose", 

372 "-v", 

373 help="Show detailed startup output and debug logs: how the [bold]FastAPI[/bold] app was discovered, imported, and configured.", 

374 ), 

375 ] = False, 

376) -> Any: 

377 """ 

378 Run a [bold]FastAPI[/bold] app in [yellow]development[/yellow] mode. 🧪 

379 

380 This is equivalent to [bold]fastapi run[/bold] but with [bold]reload[/bold] enabled and listening on the [blue]127.0.0.1[/blue] address. 

381 

382 It automatically detects the Python module or package that needs to be imported based on the file or directory path passed. 

383 

384 If no path is passed, it tries with: 

385 

386 - [blue]main.py[/blue] 

387 - [blue]app.py[/blue] 

388 - [blue]api.py[/blue] 

389 - [blue]app/main.py[/blue] 

390 - [blue]app/app.py[/blue] 

391 - [blue]app/api.py[/blue] 

392 

393 It also detects the directory that needs to be added to the [bold]PYTHONPATH[/bold] to make the app importable and adds it. 

394 

395 It detects the [bold]FastAPI[/bold] app object to use. By default it looks in the module or package for an object named: 

396 

397 - [blue]app[/blue] 

398 - [blue]api[/blue] 

399 

400 Otherwise, it uses the first [bold]FastAPI[/bold] app found in the imported module or package. 

401 """ 

402 os.environ.setdefault("FASTAPI_ENV", "development") 2sbtbubvbwbC xbybzba o Z $e%eAb0 Cb1 wexeieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 Ob4 yezejeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 Zb7 AeBekeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 !b! CeDeleS $b%b'b(bG )b*b+be s # -e.e,b$ .b% EeFeme:b;b=b?b@bH [b]b^bf t ' /e:e_b( {b) GeHene}b~bacbcccI dcecfcg u * ;e=egc+ ic, IeJeoeT kclcmcncJ ocpcqch v - ?e@erc. tc/ KeLepeU vcwcxcycK zcAcBci w : [e]eCc; Ec= MeNeqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ Pc[ OePereRcScTcUcVcM WcXcYck y ] `e{eZc^ 1c_ QeReseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ $c| SeTeteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ :cabUeVeueY =c?c@c[cP ]c^c_cn B bbbfcf`ccb|cdbWeXeve

403 

404 _run( 2sbtbubvbwbC xbybzba o Z $e%eAb0 Cb1 wexeieEbFbGbHbIbD JbKbLbb p 2 'e(eMb3 Ob4 yezejeQ QbRbSbTbE UbVbWbc q 5 )e*eXb6 Zb7 AeBekeR 1b2b3b4bF 5b6b7bd r 8 +e,e8b9 !b! CeDeleS $b%b'b(bG )b*b+be s # -e.e,b$ .b% EeFeme:b;b=b?b@bH [b]b^bf t ' /e:e_b( {b) GeHene}b~bacbcccI dcecfcg u * ;e=egc+ ic, IeJeoeT kclcmcncJ ocpcqch v - ?e@erc. tc/ KeLepeU vcwcxcycK zcAcBci w : [e]eCc; Ec= MeNeqeV GcHcIcJcL KcLcMcj x ? ^e_eNc@ Pc[ OePereRcScTcUcVcM WcXcYck y ] `e{eZc^ 1c_ QeReseW 3c4c5c6cN 7c8c9cl z ` |e}e!c{ $c| SeTeteX 'c(c)c*cO +c,c-cm A } ~eaf.c~ :cabUeVeueY =c?c@c[cP ]c^c_cn B bbbfcf`ccb|cdbWeXeve

405 path=path, 

406 host=host, 

407 port=port, 

408 reload=reload, 

409 reload_dirs=reload_dir, 

410 root_path=root_path, 

411 app=app, 

412 entrypoint=entrypoint, 

413 command="dev", 

414 proxy_headers=proxy_headers, 

415 forwarded_allow_ips=forwarded_allow_ips, 

416 public_url=os.getenv("FASTAPI_PUBLIC_URL"), 

417 verbose=verbose, 

418 ) 

419 

420 

421@app.command() 2ebfbgbhbibjbkblbmbnbobpbqbrb

422def run( 2ebfbgbQ hbibR S jbkblbT mbnbU V obpbW qbrbX Y

423 path: Annotated[ 

424 Path | None, 

425 typer.Argument( 

426 help="A path to a Python file or package directory (with [blue]__init__.py[/blue] files) containing a [bold]FastAPI[/bold] app. If not provided, a default set of paths will be tried." 

427 ), 

428 ] = None, 

429 *, 

430 host: Annotated[ 

431 str, 

432 typer.Option( 

433 help="The host to serve on. For local development in localhost use [blue]127.0.0.1[/blue]. To enable public access, e.g. in a container, use all the IP addresses available with [blue]0.0.0.0[/blue]." 

434 ), 

435 ] = "0.0.0.0", 

436 port: Annotated[ 

437 int, 

438 typer.Option( 

439 help="The port to serve on. You would normally have a termination proxy on top (another program) handling HTTPS on port [blue]443[/blue] and HTTP on port [blue]80[/blue], transferring the communication to your app.", 

440 envvar="PORT", 

441 ), 

442 ] = 8000, 

443 reload: Annotated[ 

444 bool, 

445 typer.Option( 

446 help="Enable auto-reload of the server when (code) files change. This is [bold]resource intensive[/bold], use it only during development." 

447 ), 

448 ] = False, 

449 workers: Annotated[ 

450 int | None, 

451 typer.Option( 

452 help="Use multiple worker processes. Mutually exclusive with the --reload flag." 

453 ), 

454 ] = None, 

455 root_path: Annotated[ 

456 str, 

457 typer.Option( 

458 help="The root path is used to tell your app that it is being served to the outside world with some [bold]path prefix[/bold] set up in some termination proxy or similar." 

459 ), 

460 ] = "", 

461 app: Annotated[ 

462 str | None, 

463 typer.Option( 

464 help="The name of the variable that contains the [bold]FastAPI[/bold] app in the imported module or package. If not provided, it is detected automatically." 

465 ), 

466 ] = None, 

467 entrypoint: Annotated[ 

468 str | None, 

469 typer.Option( 

470 "--entrypoint", 

471 "-e", 

472 help="The FastAPI app import string in the format 'some.importable_module:app_name'.", 

473 ), 

474 ] = None, 

475 proxy_headers: Annotated[ 

476 bool, 

477 typer.Option( 

478 help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info." 

479 ), 

480 ] = True, 

481 forwarded_allow_ips: Annotated[ 

482 str | None, 

483 typer.Option( 

484 help="Comma separated list of IP Addresses to trust with proxy headers. The literal '*' means trust everything." 

485 ), 

486 ] = None, 

487 verbose: Annotated[ 

488 bool, 

489 typer.Option( 

490 "--verbose", 

491 "-v", 

492 help="Show detailed startup output and debug logs: how the [bold]FastAPI[/bold] app was discovered, imported, and configured.", 

493 ), 

494 ] = False, 

495) -> Any: 

496 """ 

497 Run a [bold]FastAPI[/bold] app in [green]production[/green] mode. 🚀 

498 

499 This is equivalent to [bold]fastapi dev[/bold] but with [bold]reload[/bold] disabled and listening on the [blue]0.0.0.0[/blue] address. 

500 

501 It automatically detects the Python module or package that needs to be imported based on the file or directory path passed. 

502 

503 If no path is passed, it tries with: 

504 

505 - [blue]main.py[/blue] 

506 - [blue]app.py[/blue] 

507 - [blue]api.py[/blue] 

508 - [blue]app/main.py[/blue] 

509 - [blue]app/app.py[/blue] 

510 - [blue]app/api.py[/blue] 

511 

512 It also detects the directory that needs to be added to the [bold]PYTHONPATH[/bold] to make the app importable and adds it. 

513 

514 It detects the [bold]FastAPI[/bold] app object to use. By default it looks in the module or package for an object named: 

515 

516 - [blue]app[/blue] 

517 - [blue]api[/blue] 

518 

519 Otherwise, it uses the first [bold]FastAPI[/bold] app found in the imported module or package. 

520 """ 

521 _run( 20 ~cadbdcdddYeedfdBbDb3 gdhdidjdkdZeldmdNbPb6 ndodpdqdrd0esdtdYb0b9 udvdwdxdyd1ezdAd9b#b$ BdCdDdEdFd2eGdHd-b/b( IdJdKdLdMd3eNdOd`b|b+ PdQdRdSdTd4eUdVdhcjc. WdXdYdZd0d5e1d2dscuc; 3d4d5d6d7d6e8d9dDcFc@ !d#d$d%d'd7e(d)dOcQc^ *d+d,d-d.d8e/d:d0c2c{ ;d=d?d@d[d9e]d^d#c%c~ _d`d{d|d}d!e~dae/c;ccbbecedeeefe#egehe{c}c

522 path=path, 

523 host=host, 

524 port=port, 

525 reload=reload, 

526 workers=workers, 

527 root_path=root_path, 

528 app=app, 

529 entrypoint=entrypoint, 

530 command="run", 

531 proxy_headers=proxy_headers, 

532 forwarded_allow_ips=forwarded_allow_ips, 

533 public_url=os.getenv("FASTAPI_PUBLIC_URL"), 

534 verbose=verbose, 

535 ) 

536 

537 

538def main() -> None: 2ebfbgbhbibjbkblbmbnbobpbqbrb

539 app() 2ebfbgbhbibjbkblbmbnbobpbqbrb