5757 IO ,
5858 TYPE_CHECKING ,
5959 Any ,
60+ ClassVar ,
6061 Optional ,
6162 TextIO ,
6263 TypeVar ,
@@ -297,6 +298,9 @@ class Cmd(cmd.Cmd):
297298 ALPHABETICAL_SORT_KEY = utils .norm_fold
298299 NATURAL_SORT_KEY = utils .natural_keys
299300
301+ # List for storing transcript test file names
302+ testfiles : ClassVar [list [str ]] = []
303+
300304 def __init__ (
301305 self ,
302306 completekey : str = 'tab' ,
@@ -373,9 +377,9 @@ def __init__(
373377 """
374378 # Check if py or ipy need to be disabled in this instance
375379 if not include_py :
376- setattr (self , 'do_py' , None )
380+ setattr (self , 'do_py' , None ) # noqa: B010
377381 if not include_ipy :
378- setattr (self , 'do_ipy' , None )
382+ setattr (self , 'do_ipy' , None ) # noqa: B010
379383
380384 # initialize plugin system
381385 # needs to be done before we call __init__(0)
@@ -401,7 +405,7 @@ def __init__(
401405 # The maximum number of CompletionItems to display during tab completion. If the number of completion
402406 # suggestions exceeds this number, they will be displayed in the typical columnized format and will
403407 # not include the description value of the CompletionItems.
404- self .max_completion_items = 50
408+ self .max_completion_items : int = 50
405409
406410 # A dictionary mapping settable names to their Settable instance
407411 self ._settables : dict [str , Settable ] = {}
@@ -414,7 +418,7 @@ def __init__(
414418 self .build_settables ()
415419
416420 # Use as prompt for multiline commands on the 2nd+ line of input
417- self .continuation_prompt = '> '
421+ self .continuation_prompt : str = '> '
418422
419423 # Allow access to your application in embedded Python shells and scripts py via self
420424 self .self_in_py = False
@@ -445,7 +449,7 @@ def __init__(
445449 # True if running inside a Python shell or pyscript, False otherwise
446450 self ._in_py = False
447451
448- self .statement_parser = StatementParser (
452+ self .statement_parser : StatementParser = StatementParser (
449453 terminators = terminators , multiline_commands = multiline_commands , shortcuts = shortcuts
450454 )
451455
@@ -456,7 +460,7 @@ def __init__(
456460 self ._script_dir : list [str ] = []
457461
458462 # Context manager used to protect critical sections in the main thread from stopping due to a KeyboardInterrupt
459- self .sigint_protection = utils .ContextFlag ()
463+ self .sigint_protection : utils . ContextFlag = utils .ContextFlag ()
460464
461465 # If the current command created a process to pipe to, then this will be a ProcReader object.
462466 # Otherwise it will be None. It's used to know when a pipe process can be killed and/or waited upon.
@@ -551,7 +555,7 @@ def __init__(
551555 # command and category names
552556 # alias, macro, settable, and shortcut names
553557 # tab completion results when self.matches_sorted is False
554- self .default_sort_key = Cmd .ALPHABETICAL_SORT_KEY
558+ self .default_sort_key : Callable [[ str ], str ] = Cmd .ALPHABETICAL_SORT_KEY
555559
556560 ############################################################################################################
557561 # The following variables are used by tab completion functions. They are reset each time complete() is run
@@ -567,14 +571,14 @@ def __init__(
567571 self .allow_closing_quote = True
568572
569573 # An optional hint which prints above tab completion suggestions
570- self .completion_hint = ''
574+ self .completion_hint : str = ''
571575
572576 # Normally cmd2 uses readline's formatter to columnize the list of completion suggestions.
573577 # If a custom format is preferred, write the formatted completions to this string. cmd2 will
574578 # then print it instead of the readline format. ANSI style sequences and newlines are supported
575579 # when using this value. Even when using formatted_completions, the full matches must still be returned
576580 # from your completer function. ArgparseCompleter writes its tab completion tables to this string.
577- self .formatted_completions = ''
581+ self .formatted_completions : str = ''
578582
579583 # Used by complete() for readline tab completion
580584 self .completion_matches : list [str ] = []
@@ -594,10 +598,10 @@ def __init__(
594598 # Set to True before returning matches to complete() in cases where matches have already been sorted.
595599 # If False, then complete() will sort the matches using self.default_sort_key before they are displayed.
596600 # This does not affect self.formatted_completions.
597- self .matches_sorted = False
601+ self .matches_sorted : bool = False
598602
599603 # Command parsers for this Cmd instance.
600- self ._command_parsers = _CommandParsers (self )
604+ self ._command_parsers : _CommandParsers = _CommandParsers (self )
601605
602606 # Add functions decorated to be subcommands
603607 self ._register_subcommands (self )
@@ -915,7 +919,7 @@ def _register_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
915919 )
916920
917921 # iterate through all matching methods
918- for method_name , method in methods :
922+ for _method_name , method in methods :
919923 subcommand_name : str = getattr (method , constants .SUBCMD_ATTR_NAME )
920924 full_command_name : str = getattr (method , constants .SUBCMD_ATTR_COMMAND )
921925 subcmd_parser_builder = getattr (method , constants .CMD_ATTR_ARGPARSER )
@@ -952,7 +956,7 @@ def find_subcommand(action: argparse.ArgumentParser, subcmd_names: list[str]) ->
952956 if choice_name == cur_subcmd :
953957 return find_subcommand (choice , subcmd_names )
954958 break
955- raise CommandSetRegistrationError (f"Could not find subcommand '{ full_command_name } '" )
959+ raise CommandSetRegistrationError (f"Could not find subcommand '{ action } '" )
956960
957961 target_parser = find_subcommand (command_parser , subcommand_names )
958962
@@ -1021,7 +1025,7 @@ def _unregister_subcommands(self, cmdset: Union[CommandSet, 'Cmd']) -> None:
10211025 )
10221026
10231027 # iterate through all matching methods
1024- for method_name , method in methods :
1028+ for _method_name , method in methods :
10251029 subcommand_name = getattr (method , constants .SUBCMD_ATTR_NAME )
10261030 command_name = getattr (method , constants .SUBCMD_ATTR_COMMAND )
10271031
@@ -1105,8 +1109,8 @@ def remove_settable(self, name: str) -> None:
11051109 """
11061110 try :
11071111 del self ._settables [name ]
1108- except KeyError :
1109- raise KeyError (name + " is not a settable parameter" )
1112+ except KeyError as exc :
1113+ raise KeyError (name + " is not a settable parameter" ) from exc
11101114
11111115 def build_settables (self ) -> None :
11121116 """Create the dictionary of user-settable parameters."""
@@ -1119,11 +1123,11 @@ def allow_style_type(value: str) -> ansi.AllowStyle:
11191123 """Converts a string value into an ansi.AllowStyle."""
11201124 try :
11211125 return ansi .AllowStyle [value .upper ()]
1122- except KeyError :
1126+ except KeyError as esc :
11231127 raise ValueError (
11241128 f"must be { ansi .AllowStyle .ALWAYS } , { ansi .AllowStyle .NEVER } , or "
11251129 f"{ ansi .AllowStyle .TERMINAL } (case-insensitive)"
1126- )
1130+ ) from esc
11271131
11281132 self .add_settable (
11291133 Settable (
@@ -2561,7 +2565,7 @@ def onecmd_plus_hooks(
25612565 self .exit_code = ex .code
25622566 stop = True
25632567 except PassThroughException as ex :
2564- raise ex .wrapped_ex
2568+ raise ex .wrapped_ex from None
25652569 except Exception as ex : # noqa: BLE001
25662570 self .pexcept (ex )
25672571 finally :
@@ -2575,7 +2579,7 @@ def onecmd_plus_hooks(
25752579 self .exit_code = ex .code
25762580 stop = True
25772581 except PassThroughException as ex :
2578- raise ex .wrapped_ex
2582+ raise ex .wrapped_ex from None
25792583 except Exception as ex : # noqa: BLE001
25802584 self .pexcept (ex )
25812585
@@ -2896,7 +2900,7 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
28962900 # Use line buffering
28972901 new_stdout = cast (TextIO , open (utils .strip_quotes (statement .output_to ), mode = mode , buffering = 1 )) # noqa: SIM115
28982902 except OSError as ex :
2899- raise RedirectionError (f 'Failed to redirect because: { ex } ' )
2903+ raise RedirectionError ('Failed to redirect output' ) from ex
29002904
29012905 redir_saved_state .redirecting = True
29022906 sys .stdout = self .stdout = new_stdout
@@ -4059,8 +4063,8 @@ def complete_set_value(
40594063 param = arg_tokens ['param' ][0 ]
40604064 try :
40614065 settable = self .settables [param ]
4062- except KeyError :
4063- raise CompletionError (param + " is not a settable parameter" )
4066+ except KeyError as exc :
4067+ raise CompletionError (param + " is not a settable parameter" ) from exc
40644068
40654069 # Create a parser with a value field based on this settable
40664070 settable_parser = argparse_custom .DEFAULT_ARGUMENT_PARSER (parents = [Cmd .set_parser_parent ])
@@ -4528,7 +4532,7 @@ def do_ipy(self, _: argparse.Namespace) -> Optional[bool]: # pragma: no cover
45284532
45294533 # Allow users to install ipython from a cmd2 prompt when needed and still have ipy command work
45304534 try :
4531- start_ipython # noqa: F823
4535+ _dummy = start_ipython # noqa: F823
45324536 except NameError :
45334537 from IPython import start_ipython # type: ignore[import]
45344538
@@ -5145,7 +5149,7 @@ class TestMyAppCase(Cmd2TestCase):
51455149 self .poutput (f'cmd2 app: { sys .argv [0 ]} ' )
51465150 self .poutput (ansi .style (f'collected { num_transcripts } transcript{ plural } ' , bold = True ))
51475151
5148- setattr ( self .__class__ , ' testfiles' , transcripts_expanded )
5152+ self .__class__ . testfiles = transcripts_expanded
51495153 sys .argv = [sys .argv [0 ]] # the --test argument upsets unittest.main()
51505154 testcase = TestMyAppCase ()
51515155 stream = cast (TextIO , utils .StdSim (sys .stderr ))
0 commit comments