11from pathlib import Path
2+ import os
3+ import signal
24import sys
35import warnings
46
57import click
8+ from click .exceptions import ClickException , Abort
69
10+ from .. import __version__
711from ..config import APIConfig , set_config
812from ai .backend .cli .extensions import AliasGroup
913
1317@click .option ('--skip-sslcert-validation' ,
1418 help = 'Skip SSL certificate validation for all API requests.' ,
1519 is_flag = True )
16- @click .version_option ()
20+ @click .version_option (version = __version__ )
1721def main (skip_sslcert_validation ):
1822 """
1923 Backend.AI command line interface.
@@ -40,7 +44,7 @@ def run_alias():
4044 sys .argv .insert (1 , 'run' )
4145 if help :
4246 sys .argv .append ('--help' )
43- main . main ( prog_name = 'backend.ai' )
47+ run_main ( )
4448
4549
4650def _attach_command ():
@@ -51,3 +55,48 @@ def _attach_command():
5155
5256
5357_attach_command ()
58+
59+
60+ def run_main ():
61+ try :
62+ _interrupted = False
63+ main .main (
64+ standalone_mode = False ,
65+ prog_name = 'backend.ai' ,
66+ )
67+ except KeyboardInterrupt :
68+ # For interruptions outside the Click's exception handling block.
69+ print ("Interrupted!" , end = "" , file = sys .stderr )
70+ sys .stderr .flush ()
71+ _interrupted = True
72+ except Abort as e :
73+ # Click wraps unhandled KeyboardInterrupt with a plain
74+ # sys.exit(1) call and prints "Aborted!" message
75+ # (which would look non-sense to users).
76+ # This is *NOT* what we want.
77+ # Instead of relying on Click, mark the _interrupted
78+ # flag to perform our own exit routines.
79+ if isinstance (e .__context__ , KeyboardInterrupt ):
80+ print ("Interrupted!" , end = "" , file = sys .stderr )
81+ sys .stderr .flush ()
82+ _interrupted = True
83+ else :
84+ print ("Aborted!" , end = "" , file = sys .stderr )
85+ sys .stderr .flush ()
86+ sys .exit (1 )
87+ except ClickException as e :
88+ e .show ()
89+ sys .exit (e .exit_code )
90+ finally :
91+ if _interrupted :
92+ # Override the exit code when it's interrupted,
93+ # referring https://github.com/python/cpython/pull/11862
94+ if sys .platform .startswith ('win' ):
95+ # Use STATUS_CONTROL_C_EXIT to notify cmd.exe
96+ # for interrupted exit
97+ sys .exit (- 1073741510 )
98+ else :
99+ # Use the default signal handler to set the exit
100+ # code properly for interruption.
101+ signal .signal (signal .SIGINT , signal .SIG_DFL )
102+ os .kill (os .getpid (), signal .SIGINT )
0 commit comments