-
Notifications
You must be signed in to change notification settings - Fork 18
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| import signal | ||
|
|
||
| import asyncclick as click | ||
| from anyio import open_signal_receiver | ||
| from anyio.abc import CancelScope | ||
|
|
||
|
|
||
| # Reference: https://github.com/agronholm/anyio/blob/4.9.0/docs/signals.rst | ||
| async def signal_handler(scope: CancelScope): | ||
| with open_signal_receiver(signal.SIGINT, signal.SIGTERM) as signals: | ||
| async for signum in signals: | ||
| match signum: | ||
| case signal.SIGINT: | ||
| click.echo("SIGINT pressed, terminating", err=True) | ||
| case signal.SIGTERM: | ||
| click.echo("SIGTERM received, terminating", err=True) | ||
| case _: | ||
| pass | ||
|
|
||
| scope.cancel() | ||
|
|
||
| break | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,24 +1,48 @@ | ||||||||||||||||||||||||||
| import concurrent | ||||||||||||||||||||||||||
|
mangelajo marked this conversation as resolved.
|
||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||
| from contextlib import ExitStack | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import asyncclick as click | ||||||||||||||||||||||||||
| from jumpstarter_cli_common.exceptions import handle_exceptions | ||||||||||||||||||||||||||
| from anyio import create_task_group, get_cancelled_exc_class, run, to_thread | ||||||||||||||||||||||||||
| from anyio.from_thread import BlockingPortal | ||||||||||||||||||||||||||
| from jumpstarter_cli_common.exceptions import async_handle_exceptions, leaf_exceptions | ||||||||||||||||||||||||||
| from jumpstarter_cli_common.signal import signal_handler | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| from jumpstarter.utils.env import env | ||||||||||||||||||||||||||
| from jumpstarter.utils.env import env_async | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| async def j_async(): | ||||||||||||||||||||||||||
| @async_handle_exceptions | ||||||||||||||||||||||||||
| async def cli(): | ||||||||||||||||||||||||||
| async with BlockingPortal() as portal: | ||||||||||||||||||||||||||
| with ExitStack() as stack: | ||||||||||||||||||||||||||
| async with env_async(portal, stack) as client: | ||||||||||||||||||||||||||
| async with client.log_stream_async(): | ||||||||||||||||||||||||||
| await to_thread.run_sync(lambda: client.cli()(standalone_mode=False)) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||
| async with create_task_group() as tg: | ||||||||||||||||||||||||||
| tg.start_soon(signal_handler, tg.cancel_scope) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||
| await cli() | ||||||||||||||||||||||||||
| finally: | ||||||||||||||||||||||||||
| tg.cancel_scope.cancel() | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| except* click.ClickException as excgroup: | ||||||||||||||||||||||||||
| for exc in leaf_exceptions(excgroup): | ||||||||||||||||||||||||||
| exc.show() | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| sys.exit(1) | ||||||||||||||||||||||||||
|
Comment on lines
+32
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
+ except click.ClickException as exc:
+ exc.show()
+ sys.exit(1)
except* click.ClickException as excgroup:
for exc in leaf_exceptions(excgroup):
exc.show()
sys.exit(1)Failing to do so degrades the UX and breaks the contract of returning exit-code 1 on CLI errors. 📝 Committable suggestion
Suggested change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we ever get a single exception? should we catch it just in case @NickCao ?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||
| except* ( | ||||||||||||||||||||||||||
| get_cancelled_exc_class(), | ||||||||||||||||||||||||||
| concurrent.futures._base.CancelledError, | ||||||||||||||||||||||||||
| ) as _: | ||||||||||||||||||||||||||
| sys.exit(2) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| def j(): | ||||||||||||||||||||||||||
| with env() as client: | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @handle_exceptions | ||||||||||||||||||||||||||
| def cli(): | ||||||||||||||||||||||||||
| with client.log_stream(): | ||||||||||||||||||||||||||
| client.cli()(standalone_mode=False) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||
| cli() | ||||||||||||||||||||||||||
| except click.ClickException as e: | ||||||||||||||||||||||||||
| e.show() | ||||||||||||||||||||||||||
| sys.exit(1) | ||||||||||||||||||||||||||
| run(j_async) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if __name__ == "__main__": | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.