1- import inspect
21import json
32import os
3+ import threading
44from datetime import datetime , timedelta , timezone
55from pathlib import Path
66from types import SimpleNamespace
@@ -37,10 +37,6 @@ def test_is_newer_version() -> None:
3737 assert not is_newer_version ("not-a-version" , "0.17.1" )
3838
3939
40- def test_get_rich_toolkit_has_no_invocation_args_override () -> None :
41- assert "args" not in inspect .signature (get_rich_toolkit ).parameters
42-
43-
4440@respx .mock
4541def test_check_for_update_returns_update_when_pypi_has_newer_version () -> None :
4642 route = respx .get (PYPI_JSON_URL ).mock (
@@ -225,6 +221,14 @@ def test_get_upgrade_command_falls_back_when_installer_is_unknown() -> None:
225221 )
226222
227223
224+ def test_get_upgrade_command_propagates_detector_errors () -> None :
225+ def broken_detector (package_name : str ) -> None :
226+ raise RuntimeError (f"Could not inspect { package_name } " )
227+
228+ with pytest .raises (RuntimeError , match = "Could not inspect fastapi-cloud-cli" ):
229+ get_upgrade_command (detector = broken_detector )
230+
231+
228232def test_format_update_message () -> None :
229233 message = format_update_message (
230234 VersionUpdate (current = "0.17.1" , latest = "0.18.0" ),
@@ -245,41 +249,22 @@ def _seed_fresh_update_cache(latest_version: str = "999.0.0") -> None:
245249 )
246250
247251
248- def test_get_rich_toolkit_prints_forced_update_message_without_wrapper (
249- monkeypatch : pytest .MonkeyPatch ,
250- capsys : pytest .CaptureFixture [str ],
251- ) -> None :
252- monkeypatch .setenv ("FASTAPI_CLOUD_DISABLE_VERSION_CHECK" , "" )
253- _seed_fresh_update_cache ()
254-
255- with get_rich_toolkit () as toolkit :
256- toolkit .print ("command output" )
257-
258- output = capsys .readouterr ().out
259- assert "command output" in output
260- assert "update" in output
261- assert "A newer FastAPI Cloud CLI version is available" in output
262-
263-
264- def test_get_rich_toolkit_prints_forced_update_once_per_click_command () -> None :
252+ def test_get_rich_toolkit_prints_update_when_click_command_closes () -> None :
265253 @click .command ()
266- def command_with_multiple_toolkits () -> None :
267- with get_rich_toolkit () as toolkit :
268- toolkit .print ("first output" )
254+ def command_with_toolkit () -> None :
269255 with get_rich_toolkit () as toolkit :
270- toolkit .print ("second output" )
256+ toolkit .print ("command output" )
271257 click .echo ("after command body" )
272258
273259 _seed_fresh_update_cache ()
274260 result = CliRunner ().invoke (
275- command_with_multiple_toolkits ,
261+ command_with_toolkit ,
276262 [],
277263 env = {"FASTAPI_CLOUD_DISABLE_VERSION_CHECK" : "" },
278264 )
279265
280266 assert result .exit_code == 0 , result .output
281- assert "first output" in result .output
282- assert "second output" in result .output
267+ assert "command output" in result .output
283268 assert "after command body" in result .output
284269 assert result .output .count ("A newer FastAPI Cloud CLI version is available" ) == 1
285270 assert result .output .rfind ("after command body" ) < result .output .rfind ("A newer" )
@@ -322,3 +307,27 @@ def test_background_check_returns_no_message_without_update() -> None:
322307 message = check .get_update_message ()
323308
324309 assert message is None
310+
311+
312+ def test_background_check_exposes_unexpected_errors () -> None :
313+ captured_errors : list [threading .ExceptHookArgs ] = []
314+ original_hook = threading .excepthook
315+
316+ def capture_thread_error (args : threading .ExceptHookArgs ) -> None :
317+ captured_errors .append (args )
318+
319+ def broken_check () -> None :
320+ raise RuntimeError ("version check failed unexpectedly" )
321+
322+ threading .excepthook = capture_thread_error
323+ try :
324+ check = BackgroundVersionCheck (check_for_update = broken_check , join_timeout = 1 )
325+ check .start ()
326+ assert check ._thread is not None
327+ check ._thread .join (timeout = 1 )
328+ finally :
329+ threading .excepthook = original_hook
330+
331+ assert captured_errors
332+ assert captured_errors [0 ].exc_type is RuntimeError
333+ assert str (captured_errors [0 ].exc_value ) == "version check failed unexpectedly"
0 commit comments