22import logging
33import re
44import threading
5- from collections . abc import Callable
5+ from contextlib import suppress
66from dataclasses import dataclass
77from datetime import datetime , timedelta , timezone
88from pathlib import Path
99
1010import httpx
11- from detect_installer import InstallerInfo , detect_installer
11+ from detect_installer import detect_installer
1212
1313from 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
1616logger = logging .getLogger (__name__ )
1717
1818PACKAGE_NAME = "fastapi-cloud-cli"
1919DEFAULT_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"
2121VERSION_CHECK_TIMEOUT_SECONDS = 2.0
2222VERSION_CHECK_JOIN_TIMEOUT_SECONDS = 0.2
2323VERSION_CHECK_CACHE_TTL = timedelta (hours = 24 )
2424DISABLE_VERSION_CHECK_ENV = "FASTAPI_CLOUD_DISABLE_VERSION_CHECK"
25- VERSION_CHECK_CACHE_FILENAME = "version-check.json"
2625SIMPLE_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-
3934def _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
148136def 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
191170def 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
205180class 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