22
33import sys
44from argparse import ArgumentParser , Namespace
5- from typing import Optional , TYPE_CHECKING , Protocol , Any
5+ from typing import Optional , TYPE_CHECKING , Protocol , Any , Union
66
77import pkg_resources
88
9- if TYPE_CHECKING :
10- # Circumvent mypy/pylint shenanigans
11- class _SubParsersAction : # pylint: disable= too-few-public-methods # typechecker only, ignore warnings
12- def add_parser ( # pylint: disable=redefined-builtin, unused-argument # typechecker only, ignore warnings
13- self ,
14- name : str ,
15- * ,
16- prog : Optional [str ] = None ,
17- aliases : Optional [Any ] = None ,
18- help : Optional [str ] = None ,
19- ** kwargs : Any ,
20- ) -> ArgumentParser :
21- ...
9+
10+ # Circumvent mypy/pylint shenanigans ~
11+ class _SubParsersAction : # pylint: disable= too-few-public-methods # typechecker only, ignore warnings
12+ def add_parser ( # pylint: disable=redefined-builtin, unused-argument # typechecker only, ignore warnings
13+ self ,
14+ name : str ,
15+ * ,
16+ prog : Optional [str ] = None ,
17+ aliases : Optional [Any ] = None ,
18+ help : Optional [str ] = None ,
19+ ** kwargs : Any ,
20+ ) -> ArgumentParser :
21+ raise NotImplementedError
2222
2323
2424class CliEntrypoint (Protocol ): # pylint: disable= too-few-public-methods
@@ -30,24 +30,28 @@ class _CliPlugin: # pylint: disable= too-few-public-methods
3030 def __init__ (self , parser : ArgumentParser ):
3131 self .parser = parser
3232
33- def _run (self , ns : Namespace ) -> None :
33+ def _run (self , ns : Namespace ) -> int :
3434 if not hasattr (ns , "cmd" ):
3535 raise NotImplementedError (
3636 "Command defined in argparse, but it's function was not specified."
3737 )
3838 cmd = ns .cmd
39- result = cmd (ns )
39+ result : Optional [ int ] = cmd (ns )
4040 if result is None : # Assume success
4141 result = 0
42- sys . exit ( result )
42+ return result
4343
44- def run_with (self , * args : Any ) -> None :
45- ns = self .parser .parse_args (args )
46- self ._run (ns )
44+ def run_with (self , * args : Any ) -> Union [str , int , None ]:
45+ try :
46+ ns = self .parser .parse_args (args )
47+ return self ._run (ns )
48+ except SystemExit as sys_exit :
49+ return sys_exit .code
4750
4851 def run (self ) -> None :
4952 ns = self .parser .parse_args ()
50- self ._run (ns )
53+ exit_code = self ._run (ns )
54+ sys .exit (exit_code )
5155
5256
5357class CliPluginGroup (_CliPlugin ): # pylint: disable= too-few-public-methods
@@ -64,6 +68,7 @@ def __init__(
6468 parser = self ._create_parser (parent )
6569 super ().__init__ (parser )
6670 self .subparsers = self ._create_subparser_group (parser )
71+ self ._load ()
6772
6873 def _create_parser (
6974 self , command_group : Optional [_SubParsersAction ] = None
0 commit comments