Coverage for src/fastapi_cloud_cli/commands/login.py: 100%
51 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 1JKLMNOP
2from typing import Annotated, Any 1JKLMNOP
4import typer 1JKLMNOP
6from fastapi_cloud_cli._app import app, cloud_app 1JKLMNOP
7from fastapi_cloud_cli.api import APIClient 1JKLMNOP
8from fastapi_cloud_cli.commands._flow import ( 1JKLMNOP
9 DEFAULT_LOGIN_TIMEOUT_SECONDS,
10 complete_device_login,
11 device_authorization_output,
12 render_login_output,
13 start_device_authorization,
14)
15from fastapi_cloud_cli.commands.auth._app import auth_app 1JKLMNOP
16from fastapi_cloud_cli.utils.auth import Identity 1JKLMNOP
17from fastapi_cloud_cli.utils.cli import FastAPIRichToolkit, get_rich_toolkit 1JKLMNOP
18from fastapi_cloud_cli.utils.execution import JsonOutputOption 1JKLMNOP
20logger = logging.getLogger(__name__) 1JKLMNOP
23def _interactive_login( 1JKLMNOP
24 toolkit: FastAPIRichToolkit,
25 *,
26 no_open: bool = False,
27 timeout: int = DEFAULT_LOGIN_TIMEOUT_SECONDS,
28) -> Any:
29 with APIClient() as client: 1QohapCXRqibrDYSsjctEZTukdvF0UwlexG1VymfzH2WAngBI3
30 with toolkit.progress("Starting authorization", transient=True) as progress: 1QohapCXRqibrDYSsjctEZTukdvF0UwlexG1VymfzH2WAngBI3
31 with client.handle_http_errors(progress, toolkit=toolkit): 1QohapCXRqibrDYSsjctEZTukdvF0UwlexG1VymfzH2WAngBI3
32 authorization_data = start_device_authorization(client) 1QohapCXRqibrDYSsjctEZTukdvF0UwlexG1VymfzH2WAngBI3
34 url = authorization_data.verification_uri_complete 1QohapCRqibrDSsjctETukdvFUwlexGVymfzHWAngBI
36 if no_open: 1QohapCRqibrDSsjctETukdvFUwlexGVymfzHWAngBI
37 toolkit.print(f"Open {url}") 1opCqrDstEuvFwxGyzHABI
38 else:
39 launch_cmd_res = typer.launch(url) 1QhaRibSjcTkdUleVmfWng
40 logger.debug(f"Launch command result: {launch_cmd_res}") 1QhaRibSjcTkdUleVmfWng
41 toolkit.print(f"Opening [link={url}]{url}[/link]") 1QhaRibSjcTkdUleVmfWng
43 toolkit.print_line() 1QohapCRqibrDSsjctETukdvFUwlexGVymfzHWAngBI
45 with toolkit.progress( 1QohapCRqibrDSsjctETukdvFUwlexGVymfzHWAngBI
46 "Waiting for user to authorize...", transient=True
47 ) as progress:
48 result = complete_device_login( 1QohapCRqibrDSsjctETukdvFUwlexGVymfzHWAngBI
49 client=client,
50 progress=progress,
51 toolkit=toolkit,
52 device_code=authorization_data.device_code,
53 interval=authorization_data.interval,
54 timeout=timeout,
55 cancel_hint="Run `fastapi cloud login` again to retry.",
56 )
58 toolkit.success( 1QohapRqibrSsjctTukdvUwlexVymfzWAngB
59 result,
60 render_output=render_login_output,
61 )
64@app.command() 1JKLMNOP
65@cloud_app.command() 1JKLMNOP
66@auth_app.command() 1JKLMNOP
67def login( 1JK`LM{NOP|
68 no_open: Annotated[
69 bool,
70 typer.Option(
71 "--no-open",
72 help="Do not open the browser automatically.",
73 ),
74 ] = False,
75 timeout: Annotated[
76 int,
77 typer.Option(
78 "--timeout",
79 help="Maximum seconds to wait for authorization.",
80 min=10,
81 ),
82 ] = DEFAULT_LOGIN_TIMEOUT_SECONDS,
83 json_output: JsonOutputOption = False,
84) -> Any:
85 """
86 Login to FastAPI Cloud.
87 """
88 if json_output: 1#o$hapC4X%'q(ibrD5Y)*s+jctE6Z,-u.kdvF70/:w;lexG81=?y@mfzH92[]A^ngBI!3_
89 with get_rich_toolkit(json_output=json_output, minimal=True) as toolkit: 1#$%'()*+,-./:;=?@[]^_
90 with APIClient() as client: 1#$%'()*+,-./:;=?@[]^_
91 with toolkit.progress( 1#$%'()*+,-./:;=?@[]^_
92 "Starting authorization", transient=True
93 ) as progress:
94 with client.handle_http_errors(progress, toolkit=toolkit): 1#$%'()*+,-./:;=?@[]^_
95 authorization_data = start_device_authorization(client) 1#$%'()*+,-./:;=?@[]^_
97 toolkit.success(device_authorization_output(authorization_data)) 1#$%'()*+,-./:;=?@[]^_
99 return 1#$%'()*+,-./:;=?@[]^_
100 identity = Identity() 1ohapC4XqibrD5YsjctE6ZukdvF70wlexG81ymfzH92AngBI!3
102 with get_rich_toolkit() as toolkit: 1ohapC4XqibrD5YsjctE6ZukdvF70wlexG81ymfzH92AngBI!3
103 toolkit.print_title("Login to FastAPI Cloud", tag="FastAPI Cloud", emoji="🔐") 1ohapC4XqibrD5YsjctE6ZukdvF70wlexG81ymfzH92AngBI!3
104 toolkit.print_line() 1ohapC4XqibrD5YsjctE6ZukdvF70wlexG81ymfzH92AngBI!3
106 if identity.is_logged_in(): 1ohapC4XqibrD5YsjctE6ZukdvF70wlexG81ymfzH92AngBI!3
107 toolkit.print("You are already logged in.") 1456789!
108 toolkit.print_line() 1456789!
109 toolkit.print( 1456789!
110 "Run [bold]fastapi cloud logout[/bold] first if you want to switch accounts.",
111 emoji="💡",
112 )
114 return 1456789!
116 if identity.has_deploy_token(): 1ohapCXqibrDYsjctEZukdvF0wlexG1ymfzH2AngBI3
117 toolkit.print( 1abcdefg
118 "You have [bold blue]FASTAPI_CLOUD_TOKEN[/] environment variable set.\n"
119 "This token will take precedence over the user token for "
120 "[blue]`fastapi deploy`[/] command.",
121 emoji="⚠️",
122 )
123 toolkit.print_line() 1abcdefg
125 _interactive_login(toolkit, no_open=no_open, timeout=timeout) 1ohapCXqibrDYsjctEZukdvF0wlexG1ymfzH2AngBI3