Coverage for src/fastapi_cloud_cli/commands/apps/get.py: 100%
39 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-11-09 00:25 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-11-09 00:25 +0000
1import logging 1abcdefg
2from typing import Annotated, Any 1abcdefg
4import typer 1abcdefg
5from pydantic import BaseModel, Field 1abcdefg
6from rich.text import Text 1abcdefg
7from rich_toolkit import RichToolkit 1abcdefg
9from fastapi_cloud_cli.api import APIClient 1abcdefg
10from fastapi_cloud_cli.commands._auth import UserCommand, get_user_command_context 1abcdefg
11from fastapi_cloud_cli.commands.apps._app import apps_app 1abcdefg
12from fastapi_cloud_cli.commands.apps.list import ( 1abcdefg
13 App,
14 _get_app,
15 _get_app_dashboard_url,
16 _get_team,
17)
18from fastapi_cloud_cli.config import Settings 1abcdefg
19from fastapi_cloud_cli.utils.apps import resolve_app_id_or_fail 1abcdefg
20from fastapi_cloud_cli.utils.cli import get_details_table 1abcdefg
21from fastapi_cloud_cli.utils.execution import JsonOutputOption 1abcdefg
23logger = logging.getLogger(__name__) 1abcdefg
26class AppGetOutput(BaseModel): 1abcdefg
27 app: App 1abcdefg
28 dashboard_url: Annotated[str | None, Field(exclude=True)] = None 1abcdefg
31def _render_app_get_output(data: AppGetOutput, toolkit: RichToolkit) -> None: 1abhcdiefgj
32 app = data.app 1khlimnj
34 toolkit.print(f"[bold]{app.name}[/bold]", emoji="📦") 1khlimnj
35 toolkit.print_line() 1khlimnj
36 toolkit.print( 1khlimnj
37 get_details_table(
38 [
39 ("id", app.id),
40 ("slug", app.slug),
41 (
42 "directory",
43 app.directory
44 if app.directory is not None
45 else Text("-", style="dim"),
46 ),
47 ("url", app.url if app.url is not None else Text("-", style="dim")),
48 (
49 "dashboard",
50 Text(data.dashboard_url, style=f"link {data.dashboard_url}")
51 if data.dashboard_url is not None
52 else Text("-", style="dim"),
53 ),
54 ("team id", app.team_id),
55 ]
56 )
57 )
60@apps_app.command("get", cls=UserCommand) 1abcdefg
61def get_app( 1abQcdRefgS
62 ctx: typer.Context,
63 app_id: Annotated[
64 str | None,
65 typer.Argument(
66 help="ID of the app to return (defaults to the app linked to the current directory).",
67 ),
68 ] = None,
69 json_output: JsonOutputOption = False,
70) -> Any:
71 """
72 Get a FastAPI Cloud app by ID.
73 """
75 toolkit = get_user_command_context(ctx).toolkit 1opkJCqrhKDstlLEuviMFwxmNGyznOHABjPI
77 target_app_id = resolve_app_id_or_fail( 1opkJCqrhKDstlLEuviMFwxmNGyznOHABjPI
78 toolkit,
79 app_id=app_id,
80 hint="Pass an app ID or run `fastapi cloud apps create --link` first.",
81 )
83 with APIClient() as client: 1opkCqrhDstlEuviFwxmGyznHABjI
84 with toolkit.progress( 1opkCqrhDstlEuviFwxmGyznHABjI
85 title="Fetching app",
86 transient=True,
87 ) as progress:
88 with client.handle_http_errors( 1opkCqrhDstlEuviFwxmGyznHABjI
89 progress,
90 default_message="Error fetching app. Please try again later.",
91 not_found_message="App not found.",
92 toolkit=toolkit,
93 ):
94 app = _get_app(client, target_app_id) 1opkCqrhDstlEuviFwxmGyznHABjI
96 dashboard_url = None 1opkqrhstluviwxmyznABj
97 if not json_output: 1opkqrhstluviwxmyznABj
98 with toolkit.progress( 1khlimnj
99 title="Fetching team",
100 transient=True,
101 ) as progress:
102 with client.handle_http_errors( 1khlimnj
103 progress,
104 default_message="Error fetching team. Please try again later.",
105 not_found_message="Team not found.",
106 toolkit=toolkit,
107 ):
108 team = _get_team(client, app.team_id) 1khlimnj
110 dashboard_url = _get_app_dashboard_url( 1khlimnj
111 app,
112 team_slug=team.slug,
113 settings=Settings.get(),
114 )
116 result = AppGetOutput(app=app, dashboard_url=dashboard_url) 1opkqrhstluviwxmyznABj
118 toolkit.success(result, render_output=_render_app_get_output) 1opkqrhstluviwxmyznABj