|
6 | 6 | import typer |
7 | 7 | from pydantic import ValidationError |
8 | 8 | from rich import print |
| 9 | +from rich.syntax import Syntax |
9 | 10 | from rich.tree import Tree |
10 | 11 | from typer.models import CommandInfo |
11 | 12 |
|
12 | 13 | from fastapi_cli.config import FastAPIConfig |
13 | | -from fastapi_cli.discover import get_import_data, get_import_data_from_import_string |
| 14 | +from fastapi_cli.discover import ( |
| 15 | + AppConfigSource, |
| 16 | + ModuleConfigSource, |
| 17 | + get_import_data, |
| 18 | + get_import_data_from_import_string, |
| 19 | +) |
14 | 20 | from fastapi_cli.exceptions import FastAPICLIException |
15 | 21 |
|
16 | 22 | from . import __version__ |
|
22 | 28 | logger = logging.getLogger(__name__) |
23 | 29 |
|
24 | 30 |
|
| 31 | +SOURCE_DESCRIPTIONS: dict[ModuleConfigSource | AppConfigSource, str] = { |
| 32 | + "entrypoint-option": "[blue]--entrypoint[/] CLI option", |
| 33 | + "entrypoint-pyproject": "[blue]entrypoint[/] in [blue]pyproject.toml[/]", |
| 34 | + "path-argument": "[blue]path[/] CLI argument", |
| 35 | + "app-option": "[blue]--app[/] CLI option", |
| 36 | + "auto-discovery": "auto-discovery", |
| 37 | +} |
| 38 | + |
| 39 | + |
25 | 40 | try: |
26 | 41 | import uvicorn |
27 | 42 | except ImportError: # pragma: no cover |
@@ -101,6 +116,15 @@ def _load_cli_plugins(typer_app: typer.Typer) -> None: |
101 | 116 | def version_callback(value: bool) -> None: |
102 | 117 | if value: |
103 | 118 | print(f"FastAPI CLI version: [green]{__version__}[/green]") |
| 119 | + try: |
| 120 | + from fastapi_cloud_cli import ( |
| 121 | + __version__ as cloud_cli_version, |
| 122 | + ) |
| 123 | + |
| 124 | + print(f"FastAPI Cloud CLI version: [green]{cloud_cli_version}[/green]") |
| 125 | + except ImportError: # pragma: no cover |
| 126 | + pass |
| 127 | + |
104 | 128 | raise typer.Exit() |
105 | 129 |
|
106 | 130 |
|
@@ -158,6 +182,7 @@ def _run( |
158 | 182 | entrypoint: str | None = None, |
159 | 183 | proxy_headers: bool = False, |
160 | 184 | forwarded_allow_ips: str | None = None, |
| 185 | + public_url: str | None = None, |
161 | 186 | ) -> None: |
162 | 187 | with get_rich_toolkit() as toolkit: |
163 | 188 | server_type = "development" if command == "dev" else "production" |
@@ -195,7 +220,9 @@ def _run( |
195 | 220 | if path or app: |
196 | 221 | import_data = get_import_data(path=path, app_name=app) |
197 | 222 | elif config.entrypoint: |
198 | | - import_data = get_import_data_from_import_string(config.entrypoint) |
| 223 | + import_data = get_import_data_from_import_string( |
| 224 | + config.entrypoint, config.from_pyproject |
| 225 | + ) |
199 | 226 | else: |
200 | 227 | import_data = get_import_data() |
201 | 228 | except FastAPICLIException as e: |
@@ -233,7 +260,35 @@ def _run( |
233 | 260 | tag="app", |
234 | 261 | ) |
235 | 262 |
|
236 | | - url = f"http://{host}:{port}" |
| 263 | + mod_source_desc = SOURCE_DESCRIPTIONS[import_data.module_config_source] |
| 264 | + app_source_desc = SOURCE_DESCRIPTIONS[import_data.app_name_config_source] |
| 265 | + toolkit.print_line() |
| 266 | + toolkit.print("Configuration sources:", tag="info") |
| 267 | + if mod_source_desc == app_source_desc: |
| 268 | + toolkit.print(f" • Import string: {mod_source_desc}") |
| 269 | + else: |
| 270 | + toolkit.print(f" • Module: {mod_source_desc}") |
| 271 | + toolkit.print(f" • App name: {app_source_desc}") |
| 272 | + |
| 273 | + if import_data.module_config_source == "auto-discovery": |
| 274 | + toolkit.print_line() |
| 275 | + toolkit.print( |
| 276 | + "You can configure an entrypoint in [blue]pyproject.toml[/] for this app with:", |
| 277 | + tag="tip", |
| 278 | + ) |
| 279 | + toolkit.print_line() |
| 280 | + toolkit.print( |
| 281 | + Syntax( |
| 282 | + ( |
| 283 | + "[tool.fastapi]\n" |
| 284 | + f'entrypoint = "{import_data.module_data.module_import_str}:{import_data.app_name}"' |
| 285 | + ), |
| 286 | + "toml", |
| 287 | + theme="ansi_light", |
| 288 | + ) |
| 289 | + ) |
| 290 | + |
| 291 | + url = public_url.rstrip("/") if public_url else f"http://{host}:{port}" |
237 | 292 | url_docs = f"{url}/docs" |
238 | 293 |
|
239 | 294 | toolkit.print_line() |
@@ -379,6 +434,7 @@ def dev( |
379 | 434 | command="dev", |
380 | 435 | proxy_headers=proxy_headers, |
381 | 436 | forwarded_allow_ips=forwarded_allow_ips, |
| 437 | + public_url=os.getenv("FASTAPI_PUBLIC_URL"), |
382 | 438 | ) |
383 | 439 |
|
384 | 440 |
|
@@ -486,6 +542,7 @@ def run( |
486 | 542 | command="run", |
487 | 543 | proxy_headers=proxy_headers, |
488 | 544 | forwarded_allow_ips=forwarded_allow_ips, |
| 545 | + public_url=os.getenv("FASTAPI_PUBLIC_URL"), |
489 | 546 | ) |
490 | 547 |
|
491 | 548 |
|
|
0 commit comments