Coverage for src/fastapi_cloud_cli/commands/teams/list.py: 100%

52 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 1abcdefg

6from rich.markup import escape 1abcdefg

7from rich.table import Table 1abcdefg

8from rich_toolkit import RichToolkit 1abcdefg

9 

10from fastapi_cloud_cli.api import APIClient 1abcdefg

11from fastapi_cloud_cli.commands._auth import UserCommand, get_user_command_context 1abcdefg

12from fastapi_cloud_cli.commands.teams._app import teams_app 1abcdefg

13from fastapi_cloud_cli.commands.teams.get import Team, _get_team_dashboard_url 1abcdefg

14from fastapi_cloud_cli.config import Settings 1abcdefg

15from fastapi_cloud_cli.utils.execution import JsonOutputOption 1abcdefg

16 

17logger = logging.getLogger(__name__) 1abcdefg

18 

19DEFAULT_LIMIT = 100 1abcdefg

20DEFAULT_OFFSET = 0 1abcdefg

21 

22 

23class TeamsListAPIResponse(BaseModel): 1abcdefg

24 data: list[Team] 1abcdefg

25 count: int 1abcdefg

26 

27 

28class TeamsListOutput(BaseModel): 1abcdefg

29 teams: list[Team] 1abcdefg

30 total_count: int 1abcdefg

31 limit: int 1abcdefg

32 offset: int 1abcdefg

33 

34 

35def _get_teams(client: APIClient, *, limit: int, offset: int) -> TeamsListOutput: 1abcdefg

36 response = client.get( 1vCkowDhpxElqyFirzGmsAHntBIju

37 "/teams/", 

38 params={ 

39 "limit": limit, 

40 "skip": offset, 

41 }, 

42 ) 

43 response.raise_for_status() 1vCkowDhpxElqyFirzGmsAHntBIju

44 

45 data = TeamsListAPIResponse.model_validate(response.json()) 1vkowhpxlqyirzmsAntBju

46 

47 return TeamsListOutput( 1vkowhpxlqyirzmsAntBju

48 teams=data.data, 

49 total_count=data.count, 

50 limit=limit, 

51 offset=offset, 

52 ) 

53 

54 

55def _render_teams_list_output(data: TeamsListOutput, toolkit: RichToolkit) -> None: 1abhcdiefgj

56 toolkit.print_title("teams") 1kohplqirmsntju

57 toolkit.print_line() 1kohplqirmsntju

58 

59 if not data.teams: 1kohplqirmsntju

60 toolkit.print("No teams found.", bullet=False) 1opqrstu

61 return 1opqrstu

62 

63 settings = Settings.get() 1khlimnj

64 

65 table = Table.grid(padding=(0, 2), pad_edge=False) 1khlimnj

66 table.add_column("Name") 1khlimnj

67 table.add_column("ID") 1khlimnj

68 table.add_row("[bold]Name[/bold]", "[bold]ID[/bold]") 1khlimnj

69 table.add_row("", "") 1khlimnj

70 

71 for team in data.teams: 1khlimnj

72 table.add_row( 1khlimnj

73 f"[link={_get_team_dashboard_url(team, settings=settings)}]{escape(team.name)}[/link]", 

74 team.id, 

75 ) 

76 

77 toolkit.print(table, bullet=False) 1khlimnj

78 

79 

80@teams_app.command("list", cls=UserCommand) 1abcdefg

81def list_teams( 1abJcdKefgL

82 ctx: typer.Context, 

83 limit: Annotated[ 

84 int, 

85 typer.Option( 

86 "--limit", 

87 help="Maximum number of teams to return.", 

88 min=1, 

89 ), 

90 ] = DEFAULT_LIMIT, 

91 offset: Annotated[ 

92 int, 

93 typer.Option( 

94 "--offset", 

95 help="Offset into the team result set.", 

96 min=0, 

97 ), 

98 ] = DEFAULT_OFFSET, 

99 json_output: JsonOutputOption = False, 

100) -> Any: 

101 """ 

102 List FastAPI Cloud teams. 

103 """ 

104 

105 toolkit = get_user_command_context(ctx).toolkit 1vCkowDhpxElqyFirzGmsAHntBIju

106 

107 with APIClient() as client: 1vCkowDhpxElqyFirzGmsAHntBIju

108 with toolkit.progress( 1vCkowDhpxElqyFirzGmsAHntBIju

109 title="Fetching teams", 

110 transient=True, 

111 ) as progress: 

112 with client.handle_http_errors( 1vCkowDhpxElqyFirzGmsAHntBIju

113 progress, 

114 default_message="Error fetching teams. Please try again later.", 

115 toolkit=toolkit, 

116 ): 

117 result = _get_teams(client, limit=limit, offset=offset) 1vCkowDhpxElqyFirzGmsAHntBIju

118 

119 toolkit.success(result, render_output=_render_teams_list_output) 1vkowhpxlqyirzmsAntBju