@@ -203,12 +203,15 @@ def my_completer(self, text, line, begidx, endidx, arg_tokens)
203203 gettext ,
204204)
205205from typing import (
206+ IO ,
206207 Any ,
207208 Callable ,
209+ Dict ,
208210 Iterable ,
209211 List ,
210212 NoReturn ,
211213 Optional ,
214+ Sequence ,
212215 Tuple ,
213216 Type ,
214217 Union ,
@@ -220,6 +223,15 @@ def my_completer(self, text, line, begidx, endidx, arg_tokens)
220223 constants ,
221224)
222225
226+ try :
227+ from typing import (
228+ Protocol ,
229+ )
230+ except ImportError :
231+ from typing_extensions import ( # type: ignore[misc]
232+ Protocol ,
233+ )
234+
223235############################################################################################################
224236# The following are names of custom argparse argument attributes added by cmd2
225237############################################################################################################
@@ -286,6 +298,59 @@ def __init__(self, value: object, desc: str = '', *args: Any) -> None:
286298############################################################################################################
287299# Class and functions related to ChoicesCallable
288300############################################################################################################
301+
302+
303+ class ChoicesProviderFunc (Protocol ):
304+ """
305+ Function that returns a list of choices in support of tab completion
306+ """
307+
308+ def __call__ (self ) -> List [str ]:
309+ ... # pragma: no cover
310+
311+
312+ class ChoicesProviderFuncWithTokens (Protocol ):
313+ """
314+ Function that returns a list of choices in support of tab completion and accepts a dictionary of prior arguments.
315+ """
316+
317+ def __call__ (self , * , arg_tokens : Dict [str , List [str ]]) -> List [str ]:
318+ ... # pragma: no cover
319+
320+
321+ class CompleterFunc (Protocol ):
322+ """
323+ Function to support tab completion with the provided state of the user prompt
324+ """
325+
326+ def __call__ (
327+ self ,
328+ text : str ,
329+ line : str ,
330+ begidx : int ,
331+ endidx : int ,
332+ ) -> List [str ]:
333+ ... # pragma: no cover
334+
335+
336+ class CompleterFuncWithTokens (Protocol ):
337+ """
338+ Function to support tab completion with the provided state of the user prompt and accepts a dictionary of prior
339+ arguments.
340+ """
341+
342+ def __call__ (
343+ self ,
344+ text : str ,
345+ line : str ,
346+ begidx : int ,
347+ endidx : int ,
348+ * ,
349+ arg_tokens : Dict [str , List [str ]],
350+ ) -> List [str ]:
351+ ... # pragma: no cover
352+
353+
289354class ChoicesCallable :
290355 """
291356 Enables using a callable as the choices provider for an argparse argument.
@@ -295,7 +360,7 @@ class ChoicesCallable:
295360 def __init__ (
296361 self ,
297362 is_completer : bool ,
298- to_call : Union [Callable [[], List [ str ]], Callable [[ str , str , int , int ], List [ str ]] ],
363+ to_call : Union [CompleterFunc , CompleterFuncWithTokens , ChoicesProviderFunc , ChoicesProviderFuncWithTokens ],
299364 ) -> None :
300365 """
301366 Initializer
@@ -328,12 +393,18 @@ def _set_choices_callable(action: argparse.Action, choices_callable: ChoicesCall
328393 setattr (action , ATTR_CHOICES_CALLABLE , choices_callable )
329394
330395
331- def set_choices_provider (action : argparse .Action , choices_provider : Callable [[], List [str ]]) -> None :
396+ def set_choices_provider (
397+ action : argparse .Action ,
398+ choices_provider : Union [ChoicesProviderFunc , ChoicesProviderFuncWithTokens ],
399+ ) -> None :
332400 """Set choices_provider on an argparse action"""
333401 _set_choices_callable (action , ChoicesCallable (is_completer = False , to_call = choices_provider ))
334402
335403
336- def set_completer (action : argparse .Action , completer : Callable [[str , str , int , int ], List [str ]]) -> None :
404+ def set_completer (
405+ action : argparse .Action ,
406+ completer : Union [CompleterFunc , CompleterFuncWithTokens ],
407+ ) -> None :
337408 """Set completer on an argparse action"""
338409 _set_choices_callable (action , ChoicesCallable (is_completer = True , to_call = completer ))
339410
@@ -351,11 +422,11 @@ def _add_argument_wrapper(
351422 self : argparse ._ActionsContainer ,
352423 * args : Any ,
353424 nargs : Union [int , str , Tuple [int ], Tuple [int , int ], Tuple [int , float ], None ] = None ,
354- choices_provider : Optional [Callable [[], List [ str ] ]] = None ,
355- completer : Optional [Callable [[ str , str , int , int ], List [ str ] ]] = None ,
425+ choices_provider : Optional [Union [ ChoicesProviderFunc , ChoicesProviderFuncWithTokens ]] = None ,
426+ completer : Optional [Union [ CompleterFunc , CompleterFuncWithTokens ]] = None ,
356427 suppress_tab_hint : bool = False ,
357428 descriptive_header : Optional [str ] = None ,
358- ** kwargs : Any
429+ ** kwargs : Any ,
359430) -> argparse .Action :
360431 """
361432 Wrapper around _ActionsContainer.add_argument() which supports more settings used by cmd2
@@ -646,9 +717,9 @@ def _format_usage(
646717
647718 # helper for wrapping lines
648719 # noinspection PyMissingOrEmptyDocstring,PyShadowingNames
649- def get_lines (parts : List [str ], indent : str , prefix : Optional [str ] = None ):
650- lines = []
651- line = []
720+ def get_lines (parts : List [str ], indent : str , prefix : Optional [str ] = None ) -> List [ str ] :
721+ lines : List [ str ] = []
722+ line : List [ str ] = []
652723 if prefix is not None :
653724 line_len = len (prefix ) - 1
654725 else :
@@ -703,14 +774,14 @@ def get_lines(parts: List[str], indent: str, prefix: Optional[str] = None):
703774 # prefix with 'Usage:'
704775 return '%s%s\n \n ' % (prefix , usage )
705776
706- def _format_action_invocation (self , action ) -> str :
777+ def _format_action_invocation (self , action : argparse . Action ) -> str :
707778 if not action .option_strings :
708779 default = self ._get_default_metavar_for_positional (action )
709780 (metavar ,) = self ._metavar_formatter (action , default )(1 )
710781 return metavar
711782
712783 else :
713- parts = []
784+ parts : List [ str ] = []
714785
715786 # if the Optional doesn't take a value, format is:
716787 # -s, --long
@@ -729,7 +800,11 @@ def _format_action_invocation(self, action) -> str:
729800 # End cmd2 customization
730801
731802 # noinspection PyMethodMayBeStatic
732- def _determine_metavar (self , action , default_metavar ) -> Union [str , Tuple ]:
803+ def _determine_metavar (
804+ self ,
805+ action : argparse .Action ,
806+ default_metavar : Union [str , Tuple [str , ...]],
807+ ) -> Union [str , Tuple [str , ...]]:
733808 """Custom method to determine what to use as the metavar value of an action"""
734809 if action .metavar is not None :
735810 result = action .metavar
@@ -742,11 +817,15 @@ def _determine_metavar(self, action, default_metavar) -> Union[str, Tuple]:
742817 result = default_metavar
743818 return result
744819
745- def _metavar_formatter (self , action , default_metavar ) -> Callable :
820+ def _metavar_formatter (
821+ self ,
822+ action : argparse .Action ,
823+ default_metavar : Union [str , Tuple [str , ...]],
824+ ) -> Callable [[int ], Tuple [str , ...]]:
746825 metavar = self ._determine_metavar (action , default_metavar )
747826
748827 # noinspection PyMissingOrEmptyDocstring
749- def format (tuple_size ) :
828+ def format (tuple_size : int ) -> Tuple [ str , ...] :
750829 if isinstance (metavar , tuple ):
751830 return metavar
752831 else :
@@ -755,7 +834,7 @@ def format(tuple_size):
755834 return format
756835
757836 # noinspection PyProtectedMember
758- def _format_args (self , action , default_metavar ) -> str :
837+ def _format_args (self , action : argparse . Action , default_metavar : Union [ str , Tuple [ str , ...]] ) -> str :
759838 """Customized to handle ranged nargs and make other output less verbose"""
760839 metavar = self ._determine_metavar (action , default_metavar )
761840 metavar_formatter = self ._metavar_formatter (action , default_metavar )
@@ -780,7 +859,7 @@ def _format_args(self, action, default_metavar) -> str:
780859 elif isinstance (action .nargs , int ) and action .nargs > 1 :
781860 return '{}{{{}}}' .format ('%s' % metavar_formatter (1 ), action .nargs )
782861
783- return super ()._format_args (action , default_metavar )
862+ return super ()._format_args (action , default_metavar ) # type: ignore[arg-type]
784863
785864
786865# noinspection PyCompatibility
@@ -789,18 +868,18 @@ class Cmd2ArgumentParser(argparse.ArgumentParser):
789868
790869 def __init__ (
791870 self ,
792- prog = None ,
793- usage = None ,
794- description = None ,
795- epilog = None ,
796- parents = None ,
797- formatter_class = Cmd2HelpFormatter ,
798- prefix_chars = '-' ,
799- fromfile_prefix_chars = None ,
800- argument_default = None ,
801- conflict_handler = 'error' ,
802- add_help = True ,
803- allow_abbrev = True ,
871+ prog : Optional [ str ] = None ,
872+ usage : Optional [ str ] = None ,
873+ description : Optional [ str ] = None ,
874+ epilog : Optional [ str ] = None ,
875+ parents : Sequence [ argparse . ArgumentParser ] = [] ,
876+ formatter_class : Type [ argparse . HelpFormatter ] = Cmd2HelpFormatter ,
877+ prefix_chars : str = '-' ,
878+ fromfile_prefix_chars : Optional [ str ] = None ,
879+ argument_default : Optional [ str ] = None ,
880+ conflict_handler : str = 'error' ,
881+ add_help : bool = True ,
882+ allow_abbrev : bool = True ,
804883 ) -> None :
805884 super (Cmd2ArgumentParser , self ).__init__ (
806885 prog = prog ,
@@ -817,7 +896,7 @@ def __init__(
817896 allow_abbrev = allow_abbrev ,
818897 )
819898
820- def add_subparsers (self , ** kwargs ) :
899+ def add_subparsers (self , ** kwargs : Any ) -> argparse . _SubParsersAction :
821900 """
822901 Custom override. Sets a default title if one was not given.
823902
@@ -895,7 +974,7 @@ def format_help(self) -> str:
895974 # determine help from format above
896975 return formatter .format_help () + '\n '
897976
898- def _print_message (self , message , file = None ):
977+ def _print_message (self , message : str , file : Optional [ IO [ str ]] = None ) -> None :
899978 # Override _print_message to use style_aware_write() since we use ANSI escape characters to support color
900979 if message :
901980 if file is None :
@@ -923,7 +1002,7 @@ def set(self, new_val: Any) -> None:
9231002
9241003
9251004# The default ArgumentParser class for a cmd2 app
926- DEFAULT_ARGUMENT_PARSER = Cmd2ArgumentParser
1005+ DEFAULT_ARGUMENT_PARSER : Type [ argparse . ArgumentParser ] = Cmd2ArgumentParser
9271006
9281007
9291008def set_default_argument_parser (parser : Type [argparse .ArgumentParser ]) -> None :
0 commit comments