Skip to content

Commit c12ba0f

Browse files
authored
Merge pull request #701 from python-cmd2/rename
Rename load, _relative_load, and pyscript
2 parents b375999 + 6a122ae commit c12ba0f

30 files changed

+324
-306
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
* Added support for and testing with Python 3.8, starting with 3.8 beta
44
* Breaking Changes
55
* Python 3.4 reached its [end of life](https://www.python.org/dev/peps/pep-0429/) on March 18, 2019 and is no longer supported by `cmd2`
6+
* **Renamed Commands Notice**
7+
* The following commands have been renamed. The old names will be supported until the next release.
8+
* load --> run_script
9+
* _relative_load --> _relative_run_script
10+
* pyscript --> run_pyscript
611

712
## 0.9.13 (June 14, 2019)
813
* Bug Fixes

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ examples/tab_au*.py @anselor
3535
examples/tab_co*.py @kmvanbrunt
3636

3737
# Unit Tests
38-
tests/pyscript/* @anselor
38+
tests/pyscript/* @anselor @kmvanbrunt
3939
tests/transcripts/* @kotfu
4040
tests/__init__.py @kotfu
4141
tests/conftest.py @kotfu @tleonhardt

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ Click on image below to watch a short video demonstrating the capabilities of cm
2020
Main Features
2121
-------------
2222
- Searchable command history (`history` command and `<Ctrl>+r`) - optionally persistent
23-
- Text file scripting of your application with `load` (`@`) and `_relative_load` (`@@`)
24-
- Python scripting of your application with ``pyscript``
23+
- Text file scripting of your application with `run_script` (`@`) and `_relative_run_script` (`@@`)
24+
- Python scripting of your application with ``run_pyscript``
2525
- Run shell commands with ``!``
2626
- Pipe command output to shell commands with `|`
2727
- Redirect command output to file with `>`, `>>`
@@ -32,7 +32,7 @@ Main Features
3232
- Special-character command shortcuts (beyond cmd's `?` and `!`)
3333
- Command aliasing similar to bash `alias` command
3434
- Macros, which are similar to aliases, but they can contain argument placeholders
35-
- Ability to load commands at startup from an initialization script
35+
- Ability to run commands at startup from an initialization script
3636
- Settable environment parameters
3737
- Parsing commands with arguments using `argparse`, including support for sub-commands
3838
- Unicode character support
@@ -41,7 +41,7 @@ Main Features
4141
- Support for Python 3.5+ on Windows, macOS, and Linux
4242
- Trivial to provide built-in help for all commands
4343
- Built-in regression testing framework for your applications (transcript-based testing)
44-
- Transcripts for use with built-in regression can be automatically generated from `history -t` or `load -t`
44+
- Transcripts for use with built-in regression can be automatically generated from `history -t` or `run_script -t`
4545
- Alerts that seamlessly print while user enters text at prompt
4646

4747
Python 2.7 support is EOL
@@ -109,12 +109,12 @@ Instructions for implementing each feature follow.
109109
- Simple scripting using ASCII text files with one command + arguments per line
110110
- See the [Script files](https://cmd2.readthedocs.io/en/latest/freefeatures.html#script-files) section of the `cmd2` docs for more info
111111
- See [script.txt](https://github.com/python-cmd2/cmd2/blob/master/examples/scripts/script.txt) for a trivial example script that can be
112-
used in any `cmd2` application with the `load` command (or `@` shortcut)
112+
used in any `cmd2` application with the `run_script` command (or `@` shortcut)
113113

114-
- Powerful and flexible built-in Python scripting of your application using the `pyscript` command
114+
- Powerful and flexible built-in Python scripting of your application using the `run_pyscript` command
115115
- Run arbitrary Python scripts within your `cmd2` application with the ability to also call custom `cmd2` commands
116116
- No separate API for your end users to learn
117-
- Syntax for calling `cmd2` commands in a `pyscript` is essentially identical to what they would enter on the command line
117+
- Syntax for calling `cmd2` commands in a `run_pyscript` is essentially identical to what they would enter on the command line
118118
- See the [Python](https://cmd2.readthedocs.io/en/latest/freefeatures.html#python) section of the `cmd2` docs for more info
119119
- Also see the [python_scripting.py](https://github.com/python-cmd2/cmd2/blob/master/examples/python_scripting.py)
120120
example in conjunction with the [conditional.py](https://github.com/python-cmd2/cmd2/blob/master/examples/scripts/conditional.py) script

cmd2/cmd2.py

Lines changed: 101 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
were using the standard library's cmd, while enjoying the extra features.
77
88
Searchable 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
1010
Multi-line commands
11-
Special-character shortcut commands (beyond cmd's "@" and "!")
11+
Special-character shortcut commands (beyond cmd's "?" and "!")
1212
Settable environment parameters
1313
Parsing commands with `argparse` argument parsers (flags)
1414
Redirection 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).

cmd2/pyscript_bridge.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# coding=utf-8
22
"""
3-
Bridges calls made inside of pyscript with the Cmd2 host app while maintaining a reasonable
3+
Bridges calls made inside of a pyscript with the Cmd2 host app while maintaining a reasonable
44
degree of isolation between the two
55
"""
66

0 commit comments

Comments
 (0)