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
« 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
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
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
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)
29app = typer.Typer( 2ebfbgbhbibjbkblbmbnbobpbqbrb
30 rich_markup_mode="rich", context_settings={"help_option_names": ["-h", "--help"]}
31)
33logger = logging.getLogger(__name__) 2ebfbgbhbibjbkblbmbnbobpbqbrb
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}
45try: 2ebfbgbhbibjbkblbmbnbobpbqbrb
46 import uvicorn 2ebfbgbhbibjbkblbmbnbobpbqbrb
47except ImportError: # pragma: no cover
48 uvicorn = None # type: ignore[assignment]
51try: 2ebfbgbhbibjbkblbmbnbobpbqbrb
52 from fastapi_cloud_cli.cli import ( 2ebfbgbhbibjbkblbmbnbobpbqbrb
53 app as fastapi_cloud_cli,
54 )
56 app.add_typer(fastapi_cloud_cli) 2ebfbgbhbibjbkblbmbnbobpbqbrb
57except ImportError: # pragma: no cover
58 pass
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 )
66 app.add_typer(fastapi_new_cli) # pragma: no cover
67except ImportError: # pragma: no cover 2ebfbgbhbibjbkblbmbnbobpbqbrb
68 pass 2ebfbgbhbibjbkblbmbnbobpbqbrb
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 )
79 print(f"FastAPI Cloud CLI version: [green]{cloud_cli_version}[/green]") 2dfefffgfhfifjfkflfmfnfofpfqf
80 except ImportError: # pragma: no cover
81 pass
83 raise typer.Exit() 2dfefffgfhfifjfkflfmfnfofpfqf
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. 😎
99 Manage your [bold]FastAPI[/bold] projects, run your FastAPI apps, and more.
101 Read more in the docs: [link=https://fastapi.tiangolo.com/fastapi-cli/]https://fastapi.tiangolo.com/fastapi-cli/[/link].
102 """
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
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
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
113 root_tree = Tree(name) 1aobpcqdresftguhviwjxkylzmAnB
115 if root.is_dir(): 1aobpcqdresftguhviwjxkylzmAnB
116 root_tree.add("[dim]🐍 __init__.py[/dim]") 1abcdefghijklmn
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
127 return root_tree 1aobpcqdresftguhviwjxkylzmAnB
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
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
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 )
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
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
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
177 raise typer.Exit(code=1) from None 2xezeBeDeFeHeJeLeNePeReTeVeXe
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
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
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
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
206 if module_data.module_paths: 1aobpcqdresftguhviwjxkylzmAnB
207 root_tree = _get_module_tree(module_data.module_paths) 1aobpcqdresftguhviwjxkylzmAnB
209 toolkit.print(root_tree) 1aobpcqdresftguhviwjxkylzmAnB
211 toolkit.print_line() 1aobpcqdresftguhviwjxkylzmAnB
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 )
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
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 )
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
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 )
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
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
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
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
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 )
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 )
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. 🧪
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.
382 It automatically detects the Python module or package that needs to be imported based on the file or directory path passed.
384 If no path is passed, it tries with:
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]
393 It also detects the directory that needs to be added to the [bold]PYTHONPATH[/bold] to make the app importable and adds it.
395 It detects the [bold]FastAPI[/bold] app object to use. By default it looks in the module or package for an object named:
397 - [blue]app[/blue]
398 - [blue]api[/blue]
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
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 )
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. 🚀
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.
501 It automatically detects the Python module or package that needs to be imported based on the file or directory path passed.
503 If no path is passed, it tries with:
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]
512 It also detects the directory that needs to be added to the [bold]PYTHONPATH[/bold] to make the app importable and adds it.
514 It detects the [bold]FastAPI[/bold] app object to use. By default it looks in the module or package for an object named:
516 - [blue]app[/blue]
517 - [blue]api[/blue]
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 )
538def main() -> None: 2ebfbgbhbibjbkblbmbnbobpbqbrb
539 app() 2ebfbgbhbibjbkblbmbnbobpbqbrb