Skip to content

Commit 12e1fc9

Browse files
github-actions[bot]patrick91
authored andcommitted
🎨 Auto format
1 parent 0ad8909 commit 12e1fc9

7 files changed

Lines changed: 264 additions & 219 deletions

File tree

‎src/fastapi_cloud_cli/commands/login.py‎

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,48 +77,50 @@ def login() -> Any:
7777
Login to FastAPI Cloud. 🚀
7878
"""
7979
identity = Identity()
80+
is_logged_in = identity.is_logged_in()
8081

81-
if identity.is_logged_in():
82-
with get_rich_toolkit(minimal=True) as toolkit:
82+
with get_rich_toolkit(minimal=is_logged_in) as toolkit:
83+
if is_logged_in:
8384
toolkit.print("You are already logged in.")
8485
toolkit.print(
8586
"Run [bold]fastapi cloud logout[/bold] first if you want to switch accounts."
8687
)
8788

88-
return
89+
return
8990

90-
if identity.has_deploy_token():
91-
with get_rich_toolkit() as toolkit:
91+
if identity.has_deploy_token():
9292
toolkit.print(
9393
"You have [bold blue]FASTAPI_CLOUD_TOKEN[/] environment variable set.\n"
9494
"This token will take precedence over the user token for "
9595
"[blue]`fastapi deploy`[/] command.",
9696
tag="Warning",
9797
)
9898

99-
with get_rich_toolkit() as toolkit, APIClient() as client:
100-
toolkit.print_title("Login to FastAPI Cloud", tag="FastAPI")
99+
with APIClient() as client:
100+
toolkit.print_title("Login to FastAPI Cloud", tag="FastAPI")
101101

102-
toolkit.print_line()
102+
toolkit.print_line()
103103

104-
with toolkit.progress("Starting authorization") as progress:
105-
with client.handle_http_errors(progress):
106-
authorization_data = _start_device_authorization(client)
104+
with toolkit.progress("Starting authorization") as progress:
105+
with client.handle_http_errors(progress):
106+
authorization_data = _start_device_authorization(client)
107107

108-
url = authorization_data.verification_uri_complete
108+
url = authorization_data.verification_uri_complete
109109

110-
progress.log(f"Opening [link={url}]{url}[/link]")
110+
progress.log(f"Opening [link={url}]{url}[/link]")
111111

112-
toolkit.print_line()
112+
toolkit.print_line()
113113

114-
with toolkit.progress("Waiting for user to authorize...") as progress:
115-
typer.launch(url)
114+
with toolkit.progress("Waiting for user to authorize...") as progress:
115+
typer.launch(url)
116116

117-
with client.handle_http_errors(progress):
118-
access_token = _fetch_access_token(
119-
client, authorization_data.device_code, authorization_data.interval
120-
)
117+
with client.handle_http_errors(progress):
118+
access_token = _fetch_access_token(
119+
client,
120+
authorization_data.device_code,
121+
authorization_data.interval,
122+
)
121123

122-
write_auth_config(AuthConfig(access_token=access_token))
124+
write_auth_config(AuthConfig(access_token=access_token))
123125

124-
progress.log("Now you are logged in! 🚀")
126+
progress.log("Now you are logged in! 🚀")

‎src/fastapi_cloud_cli/commands/whoami.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ def whoami() -> Any:
1313

1414
with get_rich_toolkit(minimal=True) as toolkit:
1515
if not identity.is_logged_in():
16-
toolkit.print("No credentials found. Use [blue]`fastapi login`[/] to login.")
16+
toolkit.print(
17+
"No credentials found. Use [blue]`fastapi login`[/] to login."
18+
)
1719
else:
1820
with APIClient() as client:
1921
with toolkit.progress(

‎src/fastapi_cloud_cli/utils/cli.py‎

Lines changed: 12 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from types import TracebackType
44
from typing import Any, Literal
55

6-
import click
76
from rich.segment import Segment
87
from rich.style import Style
98
from rich.text import Text
@@ -16,7 +15,6 @@
1615
)
1716

1817
logger = logging.getLogger(__name__)
19-
VERSION_CHECK_CONTEXT_KEY = "fastapi_cloud_cli.version_check"
2018

2119

2220
class FastAPIStyle(TaggedStyle):
@@ -34,7 +32,9 @@ def _get_tag_segments(
3432
tag_segments, left_padding = super()._get_tag_segments(
3533
metadata, is_animated, done, animation_status=animation_status
3634
)
35+
3736
tag_style = metadata.get("tag_style")
37+
3838
if isinstance(tag_style, (str, Style)):
3939
style = self.console.get_style(tag_style)
4040
tag_segments = [
@@ -71,83 +71,42 @@ def __init__(
7171
self,
7272
style: BaseStyle | None = None,
7373
theme: RichToolkitTheme | None = None,
74-
handle_keyboard_interrupts: bool = True,
75-
print_spacing: bool = True,
7674
) -> None:
77-
super().__init__(
78-
style=style,
79-
theme=theme,
80-
handle_keyboard_interrupts=handle_keyboard_interrupts,
81-
)
82-
self._print_spacing = print_spacing
83-
self._version_check: BackgroundVersionCheck | None = None
84-
self._print_update_on_exit = False
85-
86-
def __enter__(self) -> "FastAPIRichToolkit":
75+
super().__init__(style=style, theme=theme)
8776
self._version_check = self._get_version_check()
8877

89-
if self._print_spacing:
90-
self.console.print()
91-
return self
92-
9378
def __exit__(
9479
self,
9580
exc_type: type[BaseException] | None,
9681
exc_value: BaseException | None,
9782
traceback: TracebackType | None,
9883
) -> bool | None:
99-
is_keyboard_interrupt = exc_type is KeyboardInterrupt
100-
101-
if is_keyboard_interrupt and self._version_check is not None:
102-
self._version_check.suppress()
103-
elif self._print_update_on_exit:
104-
self._print_update_message()
84+
self._print_update_message()
10585

106-
if self._print_spacing and not is_keyboard_interrupt:
107-
self.console.print()
108-
109-
if self.handle_keyboard_interrupts and is_keyboard_interrupt:
110-
return True
111-
112-
return None
86+
return super().__exit__(
87+
exc_type,
88+
exc_value,
89+
traceback,
90+
)
11391

11492
def _get_version_check(self) -> BackgroundVersionCheck | None:
11593
if os.environ.get(DISABLE_VERSION_CHECK_ENV) == "1":
11694
return None
11795

118-
context = click.get_current_context(silent=True)
119-
if context is None:
120-
version_check = BackgroundVersionCheck()
121-
version_check.start()
122-
self._print_update_on_exit = True
123-
return version_check
124-
125-
stored_version_check = context.meta.get(VERSION_CHECK_CONTEXT_KEY)
126-
if isinstance(stored_version_check, BackgroundVersionCheck):
127-
return stored_version_check
128-
12996
version_check = BackgroundVersionCheck()
13097
version_check.start()
131-
context.meta[VERSION_CHECK_CONTEXT_KEY] = version_check
132-
context.call_on_close(self._print_update_message)
13398

13499
return version_check
135100

136101
def _print_update_message(self) -> None:
137102
if self._version_check is None:
138103
return
139104

140-
message = self._version_check.get_update_message()
141-
if message:
105+
if message := self._version_check.get_update_message():
142106
self.print(Text.from_markup(message), tag="update", tag_style="tag.update")
143107

144108

145-
def get_rich_toolkit(
146-
minimal: bool = False,
147-
*,
148-
print_spacing: bool = True,
149-
handle_keyboard_interrupts: bool = True,
150-
) -> RichToolkit:
109+
def get_rich_toolkit(minimal: bool = False) -> RichToolkit:
151110
style = MinimalStyle() if minimal else FastAPIStyle(tag_width=11)
152111

153112
theme = RichToolkitTheme(
@@ -166,8 +125,4 @@ def get_rich_toolkit(
166125
},
167126
)
168127

169-
return FastAPIRichToolkit(
170-
theme=theme,
171-
handle_keyboard_interrupts=handle_keyboard_interrupts,
172-
print_spacing=print_spacing,
173-
)
128+
return FastAPIRichToolkit(theme=theme)

‎src/fastapi_cloud_cli/utils/config.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ def get_cli_config_path() -> Path:
2525
cli_config_path.parent.mkdir(parents=True, exist_ok=True)
2626

2727
return cli_config_path
28+
29+
30+
def get_version_check_cache_path() -> Path:
31+
return get_config_folder() / "version-check.json"

‎src/fastapi_cloud_cli/utils/version_check.py‎

Lines changed: 18 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,26 @@
22
import logging
33
import re
44
import threading
5-
from collections.abc import Callable
5+
from contextlib import suppress
66
from dataclasses import dataclass
77
from datetime import datetime, timedelta, timezone
88
from pathlib import Path
99

1010
import httpx
11-
from detect_installer import InstallerInfo, detect_installer
11+
from detect_installer import detect_installer
1212

1313
from fastapi_cloud_cli import __version__
14-
from fastapi_cloud_cli.utils.config import get_config_folder
14+
from fastapi_cloud_cli.utils.config import get_version_check_cache_path
1515

1616
logger = logging.getLogger(__name__)
1717

1818
PACKAGE_NAME = "fastapi-cloud-cli"
1919
DEFAULT_UPGRADE_COMMAND = f"pip install --upgrade {PACKAGE_NAME}"
20-
PYPI_JSON_URL = "https://pypi.org/pypi/fastapi-cloud-cli/json"
20+
PYPI_JSON_URL = f"https://pypi.org/pypi/{PACKAGE_NAME}/json"
2121
VERSION_CHECK_TIMEOUT_SECONDS = 2.0
2222
VERSION_CHECK_JOIN_TIMEOUT_SECONDS = 0.2
2323
VERSION_CHECK_CACHE_TTL = timedelta(hours=24)
2424
DISABLE_VERSION_CHECK_ENV = "FASTAPI_CLOUD_DISABLE_VERSION_CHECK"
25-
VERSION_CHECK_CACHE_FILENAME = "version-check.json"
2625
SIMPLE_RELEASE_VERSION_RE = re.compile(r"\d+(?:\.\d+)*")
2726

2827

@@ -32,10 +31,6 @@ class VersionUpdate:
3231
latest: str
3332

3433

35-
def get_version_check_cache_path() -> Path:
36-
return get_config_folder() / VERSION_CHECK_CACHE_FILENAME
37-
38-
3934
def _parse_simple_release_version(version: str) -> tuple[int, ...] | None:
4035
if not SIMPLE_RELEASE_VERSION_RE.fullmatch(version):
4136
logger.debug("Skipping non-simple version string: %r", version)
@@ -51,10 +46,6 @@ def is_newer_version(latest: str, current: str) -> bool:
5146
if latest_parts is None or current_parts is None:
5247
return False
5348

54-
version_length = max(len(latest_parts), len(current_parts))
55-
latest_parts += (0,) * (version_length - len(latest_parts))
56-
current_parts += (0,) * (version_length - len(current_parts))
57-
5849
return latest_parts > current_parts
5950

6051

@@ -117,11 +108,8 @@ def write_latest_version_cache(
117108
logger.debug("Could not write CLI version cache: %s", error)
118109

119110

120-
def fetch_latest_version(
121-
*,
122-
current_version: str = __version__,
123-
) -> str | None:
124-
headers = {"User-Agent": f"fastapi-cloud-cli/{current_version}"}
111+
def fetch_latest_version() -> str | None:
112+
headers = {"User-Agent": f"fastapi-cloud-cli/{__version__}"}
125113

126114
try:
127115
with httpx.Client(
@@ -147,16 +135,14 @@ def fetch_latest_version(
147135

148136
def check_for_update(
149137
*,
150-
current_version: str = __version__,
151138
cache_path: Path | None = None,
152-
now: datetime | None = None,
153139
) -> VersionUpdate | None:
154-
now = now or datetime.now(timezone.utc)
140+
now = datetime.now(timezone.utc)
155141
cache_path = cache_path or get_version_check_cache_path()
156142

157143
latest_version = read_cached_latest_version(cache_path, now=now)
158144
if latest_version is None:
159-
latest_version = fetch_latest_version(current_version=current_version)
145+
latest_version = fetch_latest_version()
160146
if latest_version is None:
161147
return None
162148

@@ -166,21 +152,14 @@ def check_for_update(
166152
now=now,
167153
)
168154

169-
if not is_newer_version(latest_version, current_version):
155+
if not is_newer_version(latest_version, __version__):
170156
return None
171157

172-
return VersionUpdate(current=current_version, latest=latest_version)
158+
return VersionUpdate(current=__version__, latest=latest_version)
173159

174160

175-
def get_upgrade_command(
176-
*,
177-
detector: Callable[[str], InstallerInfo | None] = detect_installer,
178-
) -> str:
179-
try:
180-
installer_info = detector(PACKAGE_NAME)
181-
except Exception as error:
182-
logger.debug("Could not detect CLI installer: %s", error)
183-
return DEFAULT_UPGRADE_COMMAND
161+
def get_upgrade_command() -> str:
162+
installer_info = detect_installer(PACKAGE_NAME)
184163

185164
if installer_info is None or installer_info.upgrade_cmd is None:
186165
return DEFAULT_UPGRADE_COMMAND
@@ -190,50 +169,32 @@ def get_upgrade_command(
190169

191170
def format_update_message(
192171
update: VersionUpdate,
193-
*,
194-
upgrade_command: str | None = None,
195172
) -> str:
196-
upgrade_command = upgrade_command or get_upgrade_command()
197-
198173
return (
199174
"A newer FastAPI Cloud CLI version is available: "
200175
f"{update.current} → [bold]{update.latest}[/]\n\n"
201-
f'Run "[blue]{upgrade_command}[/]" to upgrade.'
176+
f'Run "[blue]{get_upgrade_command()}[/]" to upgrade.'
202177
)
203178

204179

205180
class BackgroundVersionCheck:
206-
def __init__(
207-
self,
208-
*,
209-
check_for_update: Callable[[], VersionUpdate | None] = check_for_update,
210-
join_timeout: float = VERSION_CHECK_JOIN_TIMEOUT_SECONDS,
211-
) -> None:
212-
self._check_for_update = check_for_update
213-
self._join_timeout = join_timeout
214-
self._thread: threading.Thread | None = None
181+
def __init__(self) -> None:
182+
self._thread = threading.Thread(target=self._run, daemon=True)
215183
self._update: VersionUpdate | None = None
216184
self._message_returned = False
217185

218186
def start(self) -> None:
219-
self._thread = threading.Thread(target=self._run, daemon=True)
220187
self._thread.start()
221188

222189
def _run(self) -> None:
223-
try:
224-
self._update = self._check_for_update()
225-
except Exception as error:
226-
logger.debug("Could not check latest CLI version: %s", error)
227-
228-
def suppress(self) -> None:
229-
self._message_returned = True
190+
with suppress(Exception):
191+
self._update = check_for_update()
230192

231193
def get_update_message(self) -> str | None:
232194
if self._message_returned:
233195
return None
234196

235-
if self._thread:
236-
self._thread.join(timeout=self._join_timeout)
197+
self._thread.join(timeout=VERSION_CHECK_JOIN_TIMEOUT_SECONDS)
237198

238199
if self._update:
239200
self._message_returned = True

0 commit comments

Comments
 (0)