66were using the standard library's cmd, while enjoying the extra features.
77
88Searchable command history (commands: "history")
9- Load commands from file, save to file, edit commands in file
9+ Run commands from file, save to file, edit commands in file
1010Multi-line commands
11- Special-character shortcut commands (beyond cmd's "@ " and "!")
11+ Special-character shortcut commands (beyond cmd's "? " and "!")
1212Settable environment parameters
1313Parsing commands with `argparse` argument parsers (flags)
1414Redirection to file or paste buffer (clipboard) with > or >>
@@ -327,7 +327,7 @@ class Cmd(cmd.Cmd):
327327
328328 Line-oriented command interpreters are often useful for test harnesses, internal tools, and rapid prototypes.
329329 """
330- DEFAULT_SHORTCUTS = {'?' : 'help' , '!' : 'shell' , '@' : 'load ' , '@@' : '_relative_load ' }
330+ DEFAULT_SHORTCUTS = {'?' : 'help' , '!' : 'shell' , '@' : 'run_script ' , '@@' : '_relative_run_script ' }
331331 DEFAULT_EDITOR = utils .find_editor ()
332332
333333 def __init__ (self , completekey : str = 'tab' , stdin = None , stdout = None , * ,
@@ -343,7 +343,7 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
343343 :param stdout: (optional) alternate output file object, if not specified, sys.stdout is used
344344 :param persistent_history_file: (optional) file path to load a persistent cmd2 command history from
345345 :param persistent_history_length: (optional) max number of history items to write to the persistent history file
346- :param startup_script: (optional) file path to a a script to load and execute at startup
346+ :param startup_script: (optional) file path to a script to execute at startup
347347 :param use_ipython: (optional) should the "ipy" command be included for an embedded IPython shell
348348 :param allow_cli_args: (optional) if True, then cmd2 will process command line arguments as either
349349 commands to be run or, if -t is specified, transcript files to run.
@@ -398,7 +398,7 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
398398 'timing' : 'Report execution times' }
399399
400400 # Commands to exclude from the help menu and tab completion
401- self .hidden_commands = ['eof' , '_relative_load' ]
401+ self .hidden_commands = ['eof' , '_relative_load' , '_relative_run_script' ]
402402
403403 # Commands to exclude from the history command
404404 # initialize history
@@ -429,7 +429,7 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
429429 # Built-in commands don't make use of this. It is purely there for user-defined commands and convenience.
430430 self ._last_result = None
431431
432- # Used load command to store the current script dir as a LIFO queue to support _relative_load command
432+ # Used by run_script command to store current script dir as a LIFO queue to support _relative_run_script command
433433 self ._script_dir = []
434434
435435 # Context manager used to protect critical sections in the main thread from stopping due to a KeyboardInterrupt
@@ -460,11 +460,11 @@ def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
460460 # Commands that will run at the beginning of the command loop
461461 self ._startup_commands = []
462462
463- # If a startup script is provided, then add it in the queue to load
463+ # If a startup script is provided, then execute it in the startup commands
464464 if startup_script is not None :
465465 startup_script = os .path .abspath (os .path .expanduser (startup_script ))
466466 if os .path .exists (startup_script ) and os .path .getsize (startup_script ) > 0 :
467- self ._startup_commands .append ("load '{}'" .format (startup_script ))
467+ self ._startup_commands .append ("run_script '{}'" .format (startup_script ))
468468
469469 # Transcript files to run instead of interactive command loop
470470 self ._transcript_files = None
@@ -3240,15 +3240,15 @@ def py_quit():
32403240
32413241 return bridge .stop
32423242
3243- pyscript_parser = ACArgumentParser ()
3244- setattr (pyscript_parser .add_argument ('script_path' , help = 'path to the script file' ),
3243+ run_pyscript_parser = ACArgumentParser ()
3244+ setattr (run_pyscript_parser .add_argument ('script_path' , help = 'path to the script file' ),
32453245 ACTION_ARG_CHOICES , ('path_complete' ,))
3246- setattr (pyscript_parser .add_argument ('script_arguments' , nargs = argparse .REMAINDER ,
3247- help = 'arguments to pass to script' ),
3246+ setattr (run_pyscript_parser .add_argument ('script_arguments' , nargs = argparse .REMAINDER ,
3247+ help = 'arguments to pass to script' ),
32483248 ACTION_ARG_CHOICES , ('path_complete' ,))
32493249
3250- @with_argparser (pyscript_parser )
3251- def do_pyscript (self , args : argparse .Namespace ) -> bool :
3250+ @with_argparser (run_pyscript_parser )
3251+ def do_run_pyscript (self , args : argparse .Namespace ) -> bool :
32523252 """Run a Python script file inside the console"""
32533253 script_path = os .path .expanduser (args .script_path )
32543254 py_return = False
@@ -3270,9 +3270,16 @@ def do_pyscript(self, args: argparse.Namespace) -> bool:
32703270 finally :
32713271 # Restore command line arguments to original state
32723272 sys .argv = orig_args
3273+ if args .__statement__ .command == "pyscript" :
3274+ self .perror ("pyscript has been renamed and will be removed in the next release, "
3275+ "please use run_pyscript instead\n " ,
3276+ traceback_war = False , err_color = Fore .LIGHTYELLOW_EX )
32733277
32743278 return py_return
32753279
3280+ # pyscript is deprecated
3281+ do_pyscript = do_run_pyscript
3282+
32763283 # Only include the do_ipy() method if IPython is available on the system
32773284 if ipython_available : # pragma: no cover
32783285 @with_argparser (ACArgumentParser ())
@@ -3412,7 +3419,7 @@ def do_history(self, args: argparse.Namespace) -> Optional[bool]:
34123419 fobj .write ('{}\n ' .format (command .raw ))
34133420 try :
34143421 self .do_edit (fname )
3415- return self .do_load (fname )
3422+ return self .do_run_script (fname )
34163423 finally :
34173424 os .remove (fname )
34183425 elif args .output_file :
@@ -3623,94 +3630,115 @@ def _current_script_dir(self) -> Optional[str]:
36233630 else :
36243631 return None
36253632
3626- load_description = ("Run commands in script file that is encoded as either ASCII or UTF-8 text\n "
3627- "\n "
3628- "Script should contain one command per line, just like the command would be\n "
3629- "typed in the console.\n "
3630- "\n "
3631- "If the -r/--record_transcript flag is used, this command instead records\n "
3632- "the output of the script commands to a transcript for testing purposes.\n "
3633- )
3633+ run_script_description = ("Run commands in script file that is encoded as either ASCII or UTF-8 text\n "
3634+ "\n "
3635+ "Script should contain one command per line, just like the command would be\n "
3636+ "typed in the console.\n "
3637+ "\n "
3638+ "If the -r/--record_transcript flag is used, this command instead records\n "
3639+ "the output of the script commands to a transcript for testing purposes.\n "
3640+ )
36343641
3635- load_parser = ACArgumentParser (description = load_description )
3636- setattr (load_parser .add_argument ('-t' , '--transcript' , help = 'record the output of the script as a transcript file' ),
3642+ run_script_parser = ACArgumentParser (description = run_script_description )
3643+ setattr (run_script_parser .add_argument ('-t' , '--transcript' ,
3644+ help = 'record the output of the script as a transcript file' ),
36373645 ACTION_ARG_CHOICES , ('path_complete' ,))
3638- setattr (load_parser .add_argument ('script_path' , help = "path to the script file" ),
3646+ setattr (run_script_parser .add_argument ('script_path' , help = "path to the script file" ),
36393647 ACTION_ARG_CHOICES , ('path_complete' ,))
36403648
3641- @with_argparser (load_parser )
3642- def do_load (self , args : argparse .Namespace ) -> Optional [bool ]:
3649+ @with_argparser (run_script_parser )
3650+ def do_run_script (self , args : argparse .Namespace ) -> Optional [bool ]:
36433651 """
36443652 Run commands in script file that is encoded as either ASCII or UTF-8 text
36453653 :return: True if running of commands should stop
36463654 """
36473655 expanded_path = os .path .abspath (os .path .expanduser (args .script_path ))
36483656
3649- # Make sure the path exists and we can access it
3650- if not os .path .exists (expanded_path ):
3651- self .perror ("'{}' does not exist or cannot be accessed" .format (expanded_path ), traceback_war = False )
3652- return
3657+ # Wrap everything in a try/finally just to make sure the warning prints at end if `load` was called
3658+ try :
3659+ # Make sure the path exists and we can access it
3660+ if not os .path .exists (expanded_path ):
3661+ self .perror ("'{}' does not exist or cannot be accessed" .format (expanded_path ), traceback_war = False )
3662+ return
36533663
3654- # Make sure expanded_path points to a file
3655- if not os .path .isfile (expanded_path ):
3656- self .perror ("'{}' is not a file" .format (expanded_path ), traceback_war = False )
3657- return
3664+ # Make sure expanded_path points to a file
3665+ if not os .path .isfile (expanded_path ):
3666+ self .perror ("'{}' is not a file" .format (expanded_path ), traceback_war = False )
3667+ return
36583668
3659- # Make sure the file is not empty
3660- if os .path .getsize (expanded_path ) == 0 :
3661- self .perror ("'{}' is empty" .format (expanded_path ), traceback_war = False )
3662- return
3669+ # Make sure the file is not empty
3670+ if os .path .getsize (expanded_path ) == 0 :
3671+ self .perror ("'{}' is empty" .format (expanded_path ), traceback_war = False )
3672+ return
36633673
3664- # Make sure the file is ASCII or UTF-8 encoded text
3665- if not utils .is_text_file (expanded_path ):
3666- self .perror ("'{}' is not an ASCII or UTF-8 encoded text file" .format (expanded_path ), traceback_war = False )
3667- return
3674+ # Make sure the file is ASCII or UTF-8 encoded text
3675+ if not utils .is_text_file (expanded_path ):
3676+ self .perror ("'{}' is not an ASCII or UTF-8 encoded text file" .format (expanded_path ), traceback_war = False )
3677+ return
36683678
3669- try :
3670- # Read all lines of the script
3671- with open (expanded_path , encoding = 'utf-8' ) as target :
3672- script_commands = target .read ().splitlines ()
3673- except OSError as ex : # pragma: no cover
3674- self .perror ("Problem accessing script from '{}': {}" .format (expanded_path , ex ))
3675- return
3679+ try :
3680+ # Read all lines of the script
3681+ with open (expanded_path , encoding = 'utf-8' ) as target :
3682+ script_commands = target .read ().splitlines ()
3683+ except OSError as ex : # pragma: no cover
3684+ self .perror ("Problem accessing script from '{}': {}" .format (expanded_path , ex ))
3685+ return
36763686
3677- orig_script_dir_count = len (self ._script_dir )
3687+ orig_script_dir_count = len (self ._script_dir )
36783688
3679- try :
3680- self ._script_dir .append (os .path .dirname (expanded_path ))
3689+ try :
3690+ self ._script_dir .append (os .path .dirname (expanded_path ))
36813691
3682- if args .transcript :
3683- self ._generate_transcript (script_commands , os .path .expanduser (args .transcript ))
3684- else :
3685- return self .runcmds_plus_hooks (script_commands )
3692+ if args .transcript :
3693+ self ._generate_transcript (script_commands , os .path .expanduser (args .transcript ))
3694+ else :
3695+ return self .runcmds_plus_hooks (script_commands )
36863696
3697+ finally :
3698+ with self .sigint_protection :
3699+ # Check if a script dir was added before an exception occurred
3700+ if orig_script_dir_count != len (self ._script_dir ):
3701+ self ._script_dir .pop ()
36873702 finally :
3688- with self . sigint_protection :
3689- # Check if a script dir was added before an exception occurred
3690- if orig_script_dir_count != len ( self . _script_dir ):
3691- self . _script_dir . pop ( )
3703+ if args . __statement__ . command == "load" :
3704+ self . perror ( "load has been renamed and will be removed in the next release, "
3705+ "please use run_script instead \n " ,
3706+ traceback_war = False , err_color = Fore . LIGHTYELLOW_EX )
36923707
3693- relative_load_description = load_description
3694- relative_load_description += ("\n \n "
3695- "If this is called from within an already-running script, the filename will be\n "
3696- "interpreted relative to the already-running script's directory." )
3708+ # load has been deprecated
3709+ do_load = do_run_script
36973710
3698- relative_load_epilog = ("Notes:\n "
3699- " This command is intended to only be used within text file scripts." )
3711+ relative_run_script_description = run_script_description
3712+ relative_run_script_description += (
3713+ "\n \n "
3714+ "If this is called from within an already-running script, the filename will be\n "
3715+ "interpreted relative to the already-running script's directory." )
37003716
3701- relative_load_parser = ACArgumentParser ( description = relative_load_description , epilog = relative_load_epilog )
3702- relative_load_parser . add_argument ( 'file_path' , help = 'a file path pointing to a script' )
3717+ relative_run_script_epilog = ( "Notes: \n "
3718+ " This command is intended to only be used within text file scripts." )
37033719
3704- @with_argparser (relative_load_parser )
3705- def do__relative_load (self , args : argparse .Namespace ) -> Optional [bool ]:
3720+ relative_run_script_parser = ACArgumentParser (description = relative_run_script_description ,
3721+ epilog = relative_run_script_epilog )
3722+ relative_run_script_parser .add_argument ('file_path' , help = 'a file path pointing to a script' )
3723+
3724+ @with_argparser (relative_run_script_parser )
3725+ def do__relative_run_script (self , args : argparse .Namespace ) -> Optional [bool ]:
37063726 """
37073727 Run commands in script file that is encoded as either ASCII or UTF-8 text
37083728 :return: True if running of commands should stop
37093729 """
3730+ if args .__statement__ .command == "_relative_load" :
3731+ self .perror ("_relative_load has been renamed and will be removed in the next release, "
3732+ "please use _relative_run_script instead\n " ,
3733+ traceback_war = False , err_color = Fore .LIGHTYELLOW_EX )
3734+
37103735 file_path = args .file_path
37113736 # NOTE: Relative path is an absolute path, it is just relative to the current script directory
37123737 relative_path = os .path .join (self ._current_script_dir or '' , file_path )
3713- return self .do_load (relative_path )
3738+ return self .do_run_script (relative_path )
3739+
3740+ # _relative_load has been deprecated
3741+ do__relative_load = do__relative_run_script
37143742
37153743 def run_transcript_tests (self , transcript_paths : List [str ]) -> None :
37163744 """Runs transcript tests for provided file(s).
0 commit comments