Changed code to support older Python versions

This commit is contained in:
Malasaur 2025-12-01 23:27:09 +01:00
parent eb92d2d36f
commit 582458cdd0
5027 changed files with 794942 additions and 4 deletions

View file

@ -0,0 +1,125 @@
import logging
import time
from typing import Any
import httpx
import typer
from pydantic import BaseModel
from fastapi_cloud_cli.config import Settings
from fastapi_cloud_cli.utils.api import APIClient
from fastapi_cloud_cli.utils.auth import (
AuthConfig,
get_auth_token,
is_logged_in,
is_token_expired,
write_auth_config,
)
from fastapi_cloud_cli.utils.cli import get_rich_toolkit, handle_http_errors
from fastapi_cloud_cli.utils.pydantic_compat import model_validate_json
logger = logging.getLogger(__name__)
class AuthorizationData(BaseModel):
user_code: str
device_code: str
verification_uri: str
verification_uri_complete: str
interval: int = 5
class TokenResponse(BaseModel):
access_token: str
def _start_device_authorization(
client: httpx.Client,
) -> AuthorizationData:
settings = Settings.get()
response = client.post(
"/login/device/authorization", data={"client_id": settings.client_id}
)
response.raise_for_status()
return model_validate_json(AuthorizationData, response.text)
def _fetch_access_token(client: httpx.Client, device_code: str, interval: int) -> str:
settings = Settings.get()
while True:
response = client.post(
"/login/device/token",
data={
"device_code": device_code,
"client_id": settings.client_id,
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
},
)
if response.status_code not in (200, 400):
response.raise_for_status()
if response.status_code == 400:
data = response.json()
if data.get("error") != "authorization_pending":
response.raise_for_status()
if response.status_code == 200:
break
time.sleep(interval)
response_data = model_validate_json(TokenResponse, response.text)
return response_data.access_token
def login() -> Any:
"""
Login to FastAPI Cloud. 🚀
"""
token = get_auth_token()
if token is not None and is_token_expired(token):
with get_rich_toolkit(minimal=True) as toolkit:
toolkit.print("Your session has expired. Logging in again...")
toolkit.print_line()
if is_logged_in():
with get_rich_toolkit(minimal=True) as toolkit:
toolkit.print("You are already logged in.")
toolkit.print(
"Run [bold]fastapi cloud logout[/bold] first if you want to switch accounts."
)
return
with get_rich_toolkit() as toolkit, APIClient() as client:
toolkit.print_title("Login to FastAPI Cloud", tag="FastAPI")
toolkit.print_line()
with toolkit.progress("Starting authorization") as progress:
with handle_http_errors(progress):
authorization_data = _start_device_authorization(client)
url = authorization_data.verification_uri_complete
progress.log(f"Opening [link={url}]{url}[/link]")
toolkit.print_line()
with toolkit.progress("Waiting for user to authorize...") as progress:
typer.launch(url)
with handle_http_errors(progress):
access_token = _fetch_access_token(
client, authorization_data.device_code, authorization_data.interval
)
write_auth_config(AuthConfig(access_token=access_token))
progress.log("Now you are logged in! 🚀")