66import click
77from anyio import create_task_group , get_cancelled_exc_class , run , to_thread
88from anyio .from_thread import BlockingPortal
9- from jumpstarter_cli_common .exceptions import async_handle_exceptions , leaf_exceptions
9+ from jumpstarter_cli_common .exceptions import (
10+ ClickExceptionRed ,
11+ async_handle_exceptions ,
12+ find_exception_in_group ,
13+ leaf_exceptions ,
14+ )
1015from jumpstarter_cli_common .signal import signal_handler
1116from rich import traceback
1217
18+ from jumpstarter .common .exceptions import EnvironmentVariableNotSetError
1319from jumpstarter .utils .env import env_async
1420
1521
1622async def j_async ():
1723 @async_handle_exceptions
1824 async def cli ():
19- async with BlockingPortal () as portal :
20- with ExitStack () as stack :
21- async with env_async (portal , stack ) as client :
22- await to_thread .run_sync (lambda : client .cli ()(standalone_mode = False ))
23-
25+ try :
26+ async with BlockingPortal () as portal :
27+ with ExitStack () as stack :
28+ async with env_async (portal , stack ) as client :
29+ await to_thread .run_sync (lambda : client .cli ()(standalone_mode = False ))
30+ except BaseExceptionGroup as eg :
31+ # Handle exceptions wrapped in ExceptionGroup (e.g., from task groups)
32+ if exc := find_exception_in_group (eg , EnvironmentVariableNotSetError ):
33+ raise ClickExceptionRed (f"Error: the j command must be used inside a jmp shell: { exc } " ) from eg
34+ raise eg
2435 try :
2536 async with create_task_group () as tg :
2637 tg .start_soon (signal_handler , tg .cancel_scope )
@@ -29,7 +40,6 @@ async def cli():
2940 await cli ()
3041 finally :
3142 tg .cancel_scope .cancel ()
32-
3343 except* click .ClickException as excgroup :
3444 for exc in leaf_exceptions (excgroup ):
3545 cast (click .ClickException , exc ).show ()
0 commit comments