diff options
author | Todd Leonhardt <todd.leonhardt@gmail.com> | 2019-06-15 10:53:06 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-15 10:53:06 -0400 |
commit | c12ba0ff11b3a8fd083c641cb9149aff6494bbf9 (patch) | |
tree | a858864c091088e633de6ba6c8db55fd618a71e7 /cmd2/cmd2.py | |
parent | b3759991adca62779ef7aefbff9dc7004463e129 (diff) | |
parent | 6a122ae91b6a3fabc3709b1d488843715258e58c (diff) | |
download | cmd2-git-c12ba0ff11b3a8fd083c641cb9149aff6494bbf9.tar.gz |
Merge pull request #701 from python-cmd2/rename
Rename load, _relative_load, and pyscript
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r-- | cmd2/cmd2.py | 174 |
1 files changed, 101 insertions, 73 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 7fcb38d6..46b098c5 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -6,9 +6,9 @@ To use, simply import cmd2.Cmd instead of cmd.Cmd; use precisely as though you were using the standard library's cmd, while enjoying the extra features. Searchable command history (commands: "history") -Load commands from file, save to file, edit commands in file +Run commands from file, save to file, edit commands in file Multi-line commands -Special-character shortcut commands (beyond cmd's "@" and "!") +Special-character shortcut commands (beyond cmd's "?" and "!") Settable environment parameters Parsing commands with `argparse` argument parsers (flags) Redirection to file or paste buffer (clipboard) with > or >> @@ -327,7 +327,7 @@ class Cmd(cmd.Cmd): Line-oriented command interpreters are often useful for test harnesses, internal tools, and rapid prototypes. """ - DEFAULT_SHORTCUTS = {'?': 'help', '!': 'shell', '@': 'load', '@@': '_relative_load'} + DEFAULT_SHORTCUTS = {'?': 'help', '!': 'shell', '@': 'run_script', '@@': '_relative_run_script'} DEFAULT_EDITOR = utils.find_editor() def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *, @@ -343,7 +343,7 @@ class Cmd(cmd.Cmd): :param stdout: (optional) alternate output file object, if not specified, sys.stdout is used :param persistent_history_file: (optional) file path to load a persistent cmd2 command history from :param persistent_history_length: (optional) max number of history items to write to the persistent history file - :param startup_script: (optional) file path to a a script to load and execute at startup + :param startup_script: (optional) file path to a script to execute at startup :param use_ipython: (optional) should the "ipy" command be included for an embedded IPython shell :param allow_cli_args: (optional) if True, then cmd2 will process command line arguments as either commands to be run or, if -t is specified, transcript files to run. @@ -398,7 +398,7 @@ class Cmd(cmd.Cmd): 'timing': 'Report execution times'} # Commands to exclude from the help menu and tab completion - self.hidden_commands = ['eof', '_relative_load'] + self.hidden_commands = ['eof', '_relative_load', '_relative_run_script'] # Commands to exclude from the history command # initialize history @@ -429,7 +429,7 @@ class Cmd(cmd.Cmd): # Built-in commands don't make use of this. It is purely there for user-defined commands and convenience. self._last_result = None - # Used load command to store the current script dir as a LIFO queue to support _relative_load command + # Used by run_script command to store current script dir as a LIFO queue to support _relative_run_script command self._script_dir = [] # Context manager used to protect critical sections in the main thread from stopping due to a KeyboardInterrupt @@ -460,11 +460,11 @@ class Cmd(cmd.Cmd): # Commands that will run at the beginning of the command loop self._startup_commands = [] - # If a startup script is provided, then add it in the queue to load + # If a startup script is provided, then execute it in the startup commands if startup_script is not None: startup_script = os.path.abspath(os.path.expanduser(startup_script)) if os.path.exists(startup_script) and os.path.getsize(startup_script) > 0: - self._startup_commands.append("load '{}'".format(startup_script)) + self._startup_commands.append("run_script '{}'".format(startup_script)) # Transcript files to run instead of interactive command loop self._transcript_files = None @@ -3240,15 +3240,15 @@ class Cmd(cmd.Cmd): return bridge.stop - pyscript_parser = ACArgumentParser() - setattr(pyscript_parser.add_argument('script_path', help='path to the script file'), + run_pyscript_parser = ACArgumentParser() + setattr(run_pyscript_parser.add_argument('script_path', help='path to the script file'), ACTION_ARG_CHOICES, ('path_complete',)) - setattr(pyscript_parser.add_argument('script_arguments', nargs=argparse.REMAINDER, - help='arguments to pass to script'), + setattr(run_pyscript_parser.add_argument('script_arguments', nargs=argparse.REMAINDER, + help='arguments to pass to script'), ACTION_ARG_CHOICES, ('path_complete',)) - @with_argparser(pyscript_parser) - def do_pyscript(self, args: argparse.Namespace) -> bool: + @with_argparser(run_pyscript_parser) + def do_run_pyscript(self, args: argparse.Namespace) -> bool: """Run a Python script file inside the console""" script_path = os.path.expanduser(args.script_path) py_return = False @@ -3270,9 +3270,16 @@ class Cmd(cmd.Cmd): finally: # Restore command line arguments to original state sys.argv = orig_args + if args.__statement__.command == "pyscript": + self.perror("pyscript has been renamed and will be removed in the next release, " + "please use run_pyscript instead\n", + traceback_war=False, err_color=Fore.LIGHTYELLOW_EX) return py_return + # pyscript is deprecated + do_pyscript = do_run_pyscript + # Only include the do_ipy() method if IPython is available on the system if ipython_available: # pragma: no cover @with_argparser(ACArgumentParser()) @@ -3412,7 +3419,7 @@ class Cmd(cmd.Cmd): fobj.write('{}\n'.format(command.raw)) try: self.do_edit(fname) - return self.do_load(fname) + return self.do_run_script(fname) finally: os.remove(fname) elif args.output_file: @@ -3623,94 +3630,115 @@ class Cmd(cmd.Cmd): else: return None - load_description = ("Run commands in script file that is encoded as either ASCII or UTF-8 text\n" - "\n" - "Script should contain one command per line, just like the command would be\n" - "typed in the console.\n" - "\n" - "If the -r/--record_transcript flag is used, this command instead records\n" - "the output of the script commands to a transcript for testing purposes.\n" - ) + run_script_description = ("Run commands in script file that is encoded as either ASCII or UTF-8 text\n" + "\n" + "Script should contain one command per line, just like the command would be\n" + "typed in the console.\n" + "\n" + "If the -r/--record_transcript flag is used, this command instead records\n" + "the output of the script commands to a transcript for testing purposes.\n" + ) - load_parser = ACArgumentParser(description=load_description) - setattr(load_parser.add_argument('-t', '--transcript', help='record the output of the script as a transcript file'), + run_script_parser = ACArgumentParser(description=run_script_description) + setattr(run_script_parser.add_argument('-t', '--transcript', + help='record the output of the script as a transcript file'), ACTION_ARG_CHOICES, ('path_complete',)) - setattr(load_parser.add_argument('script_path', help="path to the script file"), + setattr(run_script_parser.add_argument('script_path', help="path to the script file"), ACTION_ARG_CHOICES, ('path_complete',)) - @with_argparser(load_parser) - def do_load(self, args: argparse.Namespace) -> Optional[bool]: + @with_argparser(run_script_parser) + def do_run_script(self, args: argparse.Namespace) -> Optional[bool]: """ Run commands in script file that is encoded as either ASCII or UTF-8 text :return: True if running of commands should stop """ expanded_path = os.path.abspath(os.path.expanduser(args.script_path)) - # Make sure the path exists and we can access it - if not os.path.exists(expanded_path): - self.perror("'{}' does not exist or cannot be accessed".format(expanded_path), traceback_war=False) - return + # Wrap everything in a try/finally just to make sure the warning prints at end if `load` was called + try: + # Make sure the path exists and we can access it + if not os.path.exists(expanded_path): + self.perror("'{}' does not exist or cannot be accessed".format(expanded_path), traceback_war=False) + return - # Make sure expanded_path points to a file - if not os.path.isfile(expanded_path): - self.perror("'{}' is not a file".format(expanded_path), traceback_war=False) - return + # Make sure expanded_path points to a file + if not os.path.isfile(expanded_path): + self.perror("'{}' is not a file".format(expanded_path), traceback_war=False) + return - # Make sure the file is not empty - if os.path.getsize(expanded_path) == 0: - self.perror("'{}' is empty".format(expanded_path), traceback_war=False) - return + # Make sure the file is not empty + if os.path.getsize(expanded_path) == 0: + self.perror("'{}' is empty".format(expanded_path), traceback_war=False) + return - # Make sure the file is ASCII or UTF-8 encoded text - if not utils.is_text_file(expanded_path): - self.perror("'{}' is not an ASCII or UTF-8 encoded text file".format(expanded_path), traceback_war=False) - return + # Make sure the file is ASCII or UTF-8 encoded text + if not utils.is_text_file(expanded_path): + self.perror("'{}' is not an ASCII or UTF-8 encoded text file".format(expanded_path), traceback_war=False) + return - try: - # Read all lines of the script - with open(expanded_path, encoding='utf-8') as target: - script_commands = target.read().splitlines() - except OSError as ex: # pragma: no cover - self.perror("Problem accessing script from '{}': {}".format(expanded_path, ex)) - return + try: + # Read all lines of the script + with open(expanded_path, encoding='utf-8') as target: + script_commands = target.read().splitlines() + except OSError as ex: # pragma: no cover + self.perror("Problem accessing script from '{}': {}".format(expanded_path, ex)) + return - orig_script_dir_count = len(self._script_dir) + orig_script_dir_count = len(self._script_dir) - try: - self._script_dir.append(os.path.dirname(expanded_path)) + try: + self._script_dir.append(os.path.dirname(expanded_path)) - if args.transcript: - self._generate_transcript(script_commands, os.path.expanduser(args.transcript)) - else: - return self.runcmds_plus_hooks(script_commands) + if args.transcript: + self._generate_transcript(script_commands, os.path.expanduser(args.transcript)) + else: + return self.runcmds_plus_hooks(script_commands) + finally: + with self.sigint_protection: + # Check if a script dir was added before an exception occurred + if orig_script_dir_count != len(self._script_dir): + self._script_dir.pop() finally: - with self.sigint_protection: - # Check if a script dir was added before an exception occurred - if orig_script_dir_count != len(self._script_dir): - self._script_dir.pop() + if args.__statement__.command == "load": + self.perror("load has been renamed and will be removed in the next release, " + "please use run_script instead\n", + traceback_war=False, err_color=Fore.LIGHTYELLOW_EX) - relative_load_description = load_description - relative_load_description += ("\n\n" - "If this is called from within an already-running script, the filename will be\n" - "interpreted relative to the already-running script's directory.") + # load has been deprecated + do_load = do_run_script - relative_load_epilog = ("Notes:\n" - " This command is intended to only be used within text file scripts.") + relative_run_script_description = run_script_description + relative_run_script_description += ( + "\n\n" + "If this is called from within an already-running script, the filename will be\n" + "interpreted relative to the already-running script's directory.") - relative_load_parser = ACArgumentParser(description=relative_load_description, epilog=relative_load_epilog) - relative_load_parser.add_argument('file_path', help='a file path pointing to a script') + relative_run_script_epilog = ("Notes:\n" + " This command is intended to only be used within text file scripts.") - @with_argparser(relative_load_parser) - def do__relative_load(self, args: argparse.Namespace) -> Optional[bool]: + relative_run_script_parser = ACArgumentParser(description=relative_run_script_description, + epilog=relative_run_script_epilog) + relative_run_script_parser.add_argument('file_path', help='a file path pointing to a script') + + @with_argparser(relative_run_script_parser) + def do__relative_run_script(self, args: argparse.Namespace) -> Optional[bool]: """ Run commands in script file that is encoded as either ASCII or UTF-8 text :return: True if running of commands should stop """ + if args.__statement__.command == "_relative_load": + self.perror("_relative_load has been renamed and will be removed in the next release, " + "please use _relative_run_script instead\n", + traceback_war=False, err_color=Fore.LIGHTYELLOW_EX) + file_path = args.file_path # NOTE: Relative path is an absolute path, it is just relative to the current script directory relative_path = os.path.join(self._current_script_dir or '', file_path) - return self.do_load(relative_path) + return self.do_run_script(relative_path) + + # _relative_load has been deprecated + do__relative_load = do__relative_run_script def run_transcript_tests(self, transcript_paths: List[str]) -> None: """Runs transcript tests for provided file(s). |