summaryrefslogtreecommitdiff
path: root/cmd2/cmd2.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r--cmd2/cmd2.py43
1 files changed, 31 insertions, 12 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 33cfe3fc..0aaeb4c3 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -3350,18 +3350,22 @@ class Cmd(cmd.Cmd):
for hi in history:
self.poutput(hi.pr(script=args.script, expanded=args.expanded, verbose=args.verbose))
- def _generate_transcript(self, history: List[HistoryItem], transcript_file: str) -> None:
+ def _generate_transcript(self, history: List[Union[HistoryItem, str]], transcript_file: str) -> None:
"""Generate a transcript file from a given history of commands."""
- # Save the current echo state, and turn it off. We inject commands into the
- # output using a different mechanism
import io
+ # Validate the transcript file path to make sure directory exists and write access is available
+ transcript_path = os.path.abspath(os.path.expanduser(transcript_file))
+ transcript_dir = os.path.dirname(transcript_path)
+ if not os.path.isdir(transcript_dir) or not os.access(transcript_dir, os.W_OK):
+ self.perror("{!r} is not a directory or you don't have write access".format(transcript_dir),
+ traceback_war=False)
+ return
+ # Disable echo while we manually redirect stdout to a StringIO buffer
saved_echo = self.echo
+ saved_stdout = self.stdout
self.echo = False
- # Redirect stdout to the transcript file
- saved_self_stdout = self.stdout
-
# The problem with supporting regular expressions in transcripts
# is that they shouldn't be processed in the command, just the output.
# In addition, when we generate a transcript, any slashes in the output
@@ -3397,10 +3401,9 @@ class Cmd(cmd.Cmd):
# and add the regex-escaped output to the transcript
transcript += output.replace('/', r'\/')
- # Restore stdout to its original state
- self.stdout = saved_self_stdout
- # Set echo back to its original state
+ # Restore altered attributes to their original state
self.echo = saved_echo
+ self.stdout = saved_stdout
# finally, we can write the transcript out to the file
try:
@@ -3456,9 +3459,20 @@ class Cmd(cmd.Cmd):
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.")
+ "typed in the console.\n"
+ "\n"
+ "It loads commands from a script file into a queue and then the normal cmd2\n"
+ "REPL resumes control and executes the commands in the queue in FIFO order.\n"
+ "If you attempt to redirect/pipe a load command, it will capture the output\n"
+ "of the load command itself, not what it adds to the queue.\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'),
+ ACTION_ARG_CHOICES, ('path_complete',))
setattr(load_parser.add_argument('script_path', help="path to the script file"),
ACTION_ARG_CHOICES, ('path_complete',))
@@ -3492,11 +3506,16 @@ class Cmd(cmd.Cmd):
# command queue. Add an "end of script (eos)" command to cleanup the
# self._script_dir list when done.
with open(expanded_path, encoding='utf-8') as target:
- self.cmdqueue = target.read().splitlines() + ['eos'] + self.cmdqueue
+ script_commands = target.read().splitlines()
except OSError as ex: # pragma: no cover
self.perror("Problem accessing script from '{}': {}".format(expanded_path, ex))
return
+ if args.transcript:
+ self._generate_transcript(script_commands, os.path.expanduser(args.transcript))
+ return
+
+ self.cmdqueue = script_commands + ['eos'] + self.cmdqueue
self._script_dir.append(os.path.dirname(expanded_path))
relative_load_description = load_description
@@ -3812,7 +3831,7 @@ class Cmd(cmd.Cmd):
# If transcript-based regression testing was requested, then do that instead of the main loop
if self._transcript_files is not None:
- self.run_transcript_tests(self._transcript_files)
+ self.run_transcript_tests([os.path.expanduser(tf) for tf in self._transcript_files])
else:
# If an intro was supplied in the method call, allow it to override the default
if intro is not None: