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

1import logging 1abcdefg

2from typing import Annotated, Any 1abcdefg

3 

4import typer 1abcdefg

5from pydantic import BaseModel, Field 1abcdefg

6from rich.text import Text 1abcdefg

7from rich_toolkit import RichToolkit 1abcdefg

8 

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

22 

23logger = logging.getLogger(__name__) 1abcdefg

24 

25 

26class AppGetOutput(BaseModel): 1abcdefg

27 app: App 1abcdefg

28 dashboard_url: Annotated[str | None, Field(exclude=True)] = None 1abcdefg

29 

30 

31def _render_app_get_output(data: AppGetOutput, toolkit: RichToolkit) -> None: 1abhcdiefgj

32 app = data.app 1khlimnj

33 

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 ) 

58 

59 

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 """ 

74 

75 toolkit = get_user_command_context(ctx).toolkit 1opkJCqrhKDstlLEuviMFwxmNGyznOHABjPI

76 

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 ) 

82 

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

95 

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

109 

110 dashboard_url = _get_app_dashboard_url( 1khlimnj

111 app, 

112 team_slug=team.slug, 

113 settings=Settings.get(), 

114 ) 

115 

116 result = AppGetOutput(app=app, dashboard_url=dashboard_url) 1opkqrhstluviwxmyznABj

117 

118 toolkit.success(result, render_output=_render_app_get_output) 1opkqrhstluviwxmyznABj