1111import  argparse 
1212import  asyncio 
1313import  inspect 
14+ import  logging 
1415from  enum  import  Enum 
1516from  typing  import  (
1617    Any ,
4647
4748
4849class  ParserBase :
49-     """ 
50-     Base class for handling parsers. 
51-     """ 
50+     """Base class for handling parsers.""" 
5251
5352    def  __init__ (self , parser : argparse .ArgumentParser ):
5453        self .parser  =  parser 
@@ -60,8 +59,7 @@ def argument(self, *name_or_flags, **kwargs) -> argparse.Action:
6059        return  self .parser .add_argument (* name_or_flags , ** kwargs )
6160
6261    def  argument_group (self , * , title : str  =  None , description : str  =  None ):
63-         """ 
64-         Add an argument group to proxy 
62+         """Add an argument group to proxy. 
6563
6664        See: https://docs.python.org/3.6/library/argparse.html#argument-groups 
6765
@@ -70,8 +68,7 @@ def argument_group(self, *, title: str = None, description: str = None):
7068
7169
7270class  CommandProxy (ParserBase ):
73-     """ 
74-     Proxy object that wraps a handler. 
71+     """Proxy object that wraps a handler. 
7572
7673    .. versionupdated:: 4.4 
7774        Determine arguments from handler signature. 
@@ -80,15 +77,14 @@ class CommandProxy(ParserBase):
8077
8178    __slots__  =  ("__name__" , "handler" , "_args" , "_require_namespace" )
8279
83-     def  __init__ (self , handler : Handler , parser : argparse .ArgumentParser ):
84-         """ 
85-         Initialise proxy 
80+     def  __init__ (self , handler : Handler , parser : argparse .ArgumentParser , loglevel : int  =  logging .INFO ):
81+         """Initialise proxy. 
8682
8783        :param handler: Callable object that accepts a single argument. 
88- 
8984        """ 
9085        super ().__init__ (parser )
9186        self .handler  =  handler 
87+         self .loglevel  =  loglevel 
9288
9389        # Copy details 
9490        self .__doc__  =  handler .__doc__ 
@@ -108,9 +104,7 @@ def __init__(self, handler: Handler, parser: argparse.ArgumentParser):
108104        self ._extract_args (handler )
109105
110106    def  _extract_args (self , func ):
111-         """ 
112-         Extract args from signature and turn into command line args 
113-         """ 
107+         """Extract args from signature and turn into command line args.""" 
114108        sig  =  inspect .signature (func )
115109
116110        # Backwards compatibility 
@@ -144,26 +138,21 @@ def __call__(self, opts: argparse.Namespace):
144138
145139
146140class  AsyncCommandProxy (CommandProxy ):
147-     """ 
148-     Proxy object that wraps an async handler. 
141+     """Proxy object that wraps an async handler. 
149142
150-     Will handle starting a  event loop. 
143+     Will handle starting an  event loop. 
151144    """ 
152145
153146    def  __call__ (self , opts : argparse .Namespace ):
154147        return  async_run (super ().__call__ (opts ))
155148
156149
157150class  ArgumentType (abc .ABC ):
158-     """ 
159-     Custom argument type 
160-     """ 
151+     """Custom argument type.""" 
161152
162153    @abc .abstractmethod  
163154    def  __call__ (self , value : str ) ->  Any :
164-         """ 
165-         Construct a value from type 
166-         """ 
155+         """Construct a value from type.""" 
167156
168157
169158class  Argument :
@@ -417,9 +406,7 @@ def register_with_proxy(self, proxy: CommandProxy) -> argparse.Action:
417406
418407
419408class  CommandGroup (ParserBase ):
420-     """ 
421-     Group of commands. 
422-     """ 
409+     """Group of commands.""" 
423410
424411    def  __init__ (
425412        self ,
@@ -436,9 +423,7 @@ def __init__(
436423
437424    @cached_property  
438425    def  handler_dest (self ) ->  str :
439-         """ 
440-         Destination of handler 
441-         """ 
426+         """Destination of handler.""" 
442427        return  f":handler:{ self ._prefix  or  '' }  " 
443428
444429    def  _add_handler (self , handler , name , aliases ):
@@ -454,8 +439,7 @@ def _add_handler(self, handler, name, aliases):
454439    def  create_command_group (
455440        self , name : str , * , aliases : Sequence [str ] =  (), help_text : str  =  None 
456441    ) ->  "CommandGroup" :
457-         """ 
458-         Create a command group 
442+         """Create a command group. 
459443
460444        :param name: Name of the command group 
461445        :param aliases: A sequence a name aliases for this command group. 
@@ -481,19 +465,23 @@ def command(
481465        name : str  =  None ,
482466        aliases : Sequence [str ] =  (),
483467        help_text : str  =  None ,
468+         loglevel : int  =  logging .INFO 
484469    ) ->  CommandProxy :
485-         """ 
486-         Decorator for registering handlers. 
470+         """Decorator for registering handlers. 
487471
488472        :param handler: Handler function 
489473        :param name: Optional name to use for CLI; defaults to the function name. 
490474        :param aliases: A sequence a name aliases for this command. 
491475        :param help_text: Information provided to the user if help is invoked; 
492476            default is taken from the handlers doc string. 
477+         :param loglevel: The default log-level when using this command. 
493478
494479        .. versionchanged:: 4.3 
495480            Async handlers supported. 
496481
482+         .. versionchanged:: 4.15 
483+             Add loglevel option to allow per-command log levels to be set. 
484+ 
497485        """ 
498486
499487        def  inner (func : Handler ) ->  CommandProxy :
@@ -520,8 +508,7 @@ def inner(func: Handler) -> CommandProxy:
520508        return  inner (handler ) if  handler  else  inner 
521509
522510    def  default (self , handler : Handler ):
523-         """ 
524-         Decorator for registering a default handler. 
511+         """Decorator for registering a default handler. 
525512
526513        .. versionchanged:: 4.3 
527514            Async handlers supported. 
@@ -534,21 +521,19 @@ def default(self, handler: Handler):
534521        return  handler 
535522
536523    def  default_handler (self , _ : argparse .Namespace ) ->  int :
537-         """ 
538-         Handler called if no handler is specified 
539-         """ 
524+         """Handler called if no handler is specified.""" 
540525        print ("No command specified!" )
541526        self .parser .print_usage ()
542527        return  1 
543528
544-     def  dispatch_handler (self , opts : argparse .Namespace ) ->  int :
545-         """ 
546-         Resolve the correct handler and call it with supplied options namespace. 
547-         """ 
529+     def  resolve_handler (self , opts : argparse .Namespace ) ->  Handler :
530+         """Resolve a command handler.""" 
548531        handler_name  =  getattr (opts , self .handler_dest , None )
549- 
550532        if  self ._prefix :
551533            handler_name  =  f"{ self ._prefix }  :{ handler_name }  " 
552-         handler   =  self ._handlers .get (handler_name , self ._default_handler )
534+         return  self ._handlers .get (handler_name , self ._default_handler )
553535
536+     def  dispatch_handler (self , opts : argparse .Namespace ) ->  int :
537+         """Resolve the correct handler and call it with supplied options namespace.""" 
538+         handler  =  self .resolve_handler (opts )
554539        return  handler (opts )
0 commit comments