Skip to content

Commit 5b9e999

Browse files
kmvanbruntanselor
authored andcommitted
Replaced some pexcept() calls with perror().
Converted some strings to f-strings. Fixed some grammar in error messages and docs. Increased code coverage.
1 parent 9e62a0a commit 5b9e999

File tree

8 files changed

+46
-58
lines changed

8 files changed

+46
-58
lines changed

cmd2/cmd2.py

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2674,7 +2674,7 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
26742674
# Use line buffering
26752675
new_stdout = cast(TextIO, open(utils.strip_quotes(statement.output_to), mode=mode, buffering=1))
26762676
except OSError as ex:
2677-
raise RedirectionError('Failed to redirect because - {}'.format(ex))
2677+
raise RedirectionError(f'Failed to redirect because: {ex}')
26782678

26792679
redir_saved_state.redirecting = True
26802680
sys.stdout = self.stdout = new_stdout
@@ -4309,13 +4309,13 @@ def do_history(self, args: argparse.Namespace) -> Optional[bool]:
43094309
# -v must be used alone with no other options
43104310
if args.verbose:
43114311
if args.clear or args.edit or args.output_file or args.run or args.transcript or args.expanded or args.script:
4312-
self.poutput("-v can not be used with any other options")
4312+
self.poutput("-v cannot be used with any other options")
43134313
self.poutput(self.history_parser.format_usage())
43144314
return None
43154315

43164316
# -s and -x can only be used if none of these options are present: [-c -r -e -o -t]
43174317
if (args.script or args.expanded) and (args.clear or args.edit or args.output_file or args.run or args.transcript):
4318-
self.poutput("-s and -x can not be used with -c, -r, -e, -o, or -t")
4318+
self.poutput("-s and -x cannot be used with -c, -r, -e, -o, or -t")
43194319
self.poutput(self.history_parser.format_usage())
43204320
return None
43214321

@@ -4329,7 +4329,7 @@ def do_history(self, args: argparse.Namespace) -> Optional[bool]:
43294329
except FileNotFoundError:
43304330
pass
43314331
except OSError as ex:
4332-
self.pexcept("Error removing history file '{}': {}".format(self.persistent_history_file, ex))
4332+
self.perror(f"Error removing history file '{self.persistent_history_file}': {ex}")
43334333
return None
43344334

43354335
if rl_type != RlType.NONE:
@@ -4352,28 +4352,29 @@ def do_history(self, args: argparse.Namespace) -> Optional[bool]:
43524352
with os.fdopen(fd, 'w') as fobj:
43534353
for command in history.values():
43544354
if command.statement.multiline_command:
4355-
fobj.write('{}\n'.format(command.expanded))
4355+
fobj.write(f'{command.expanded}\n')
43564356
else:
4357-
fobj.write('{}\n'.format(command.raw))
4357+
fobj.write(f'{command.raw}\n')
43584358
try:
43594359
self._run_editor(fname)
43604360
# noinspection PyTypeChecker
43614361
self.do_run_script(utils.quote_string(fname))
43624362
finally:
43634363
os.remove(fname)
43644364
elif args.output_file:
4365+
full_path = os.path.abspath(os.path.expanduser(args.output_file))
43654366
try:
4366-
with open(os.path.expanduser(args.output_file), 'w') as fobj:
4367+
with open(full_path, 'w') as fobj:
43674368
for item in history.values():
43684369
if item.statement.multiline_command:
4369-
fobj.write('{}\n'.format(item.expanded))
4370+
fobj.write(f"{item.expanded}\n")
43704371
else:
4371-
fobj.write('{}\n'.format(item.raw))
4372+
fobj.write(f"{item.raw}\n")
43724373
plural = 's' if len(history) > 1 else ''
4373-
except OSError as e:
4374-
self.pexcept('Error saving {!r} - {}'.format(args.output_file, e))
4374+
except OSError as ex:
4375+
self.perror(f"Error saving history file '{full_path}': {ex}")
43754376
else:
4376-
self.pfeedback('{} command{} saved to {}'.format(len(history), plural, args.output_file))
4377+
self.pfeedback(f"{len(history)} command{plural} saved to {full_path}")
43774378
elif args.transcript:
43784379
self._generate_transcript(list(history.values()), args.transcript)
43794380
else:
@@ -4426,20 +4427,18 @@ def _initialize_history(self, hist_file: str) -> None:
44264427

44274428
hist_file = os.path.abspath(os.path.expanduser(hist_file))
44284429

4429-
# on Windows, trying to open a directory throws a permission
4430+
# On Windows, trying to open a directory throws a permission
44304431
# error, not a `IsADirectoryError`. So we'll check it ourselves.
44314432
if os.path.isdir(hist_file):
4432-
msg = "Persistent history file '{}' is a directory"
4433-
self.perror(msg.format(hist_file))
4433+
self.perror(f"Persistent history file '{hist_file}' is a directory")
44344434
return
44354435

44364436
# Create the directory for the history file if it doesn't already exist
44374437
hist_file_dir = os.path.dirname(hist_file)
44384438
try:
44394439
os.makedirs(hist_file_dir, exist_ok=True)
44404440
except OSError as ex:
4441-
msg = "Error creating persistent history file directory '{}': {}".format(hist_file_dir, ex)
4442-
self.pexcept(msg)
4441+
self.perror(f"Error creating persistent history file directory '{hist_file_dir}': {ex}")
44434442
return
44444443

44454444
# first we try and unpickle the history file
@@ -4461,8 +4460,7 @@ def _initialize_history(self, hist_file: str) -> None:
44614460
# If any of these errors occur when attempting to unpickle, just use an empty history
44624461
pass
44634462
except OSError as ex:
4464-
msg = "Can not read persistent history file '{}': {}"
4465-
self.pexcept(msg.format(hist_file, ex))
4463+
self.perror(f"Cannot read persistent history file '{hist_file}': {ex}")
44664464
return
44674465

44684466
self.history = history
@@ -4498,16 +4496,15 @@ def _persist_history(self) -> None:
44984496
with open(self.persistent_history_file, 'wb') as fobj:
44994497
pickle.dump(self.history, fobj)
45004498
except OSError as ex:
4501-
msg = "Can not write persistent history file '{}': {}"
4502-
self.pexcept(msg.format(self.persistent_history_file, ex))
4499+
self.perror(f"Cannot write persistent history file '{self.persistent_history_file}': {ex}")
45034500

45044501
def _generate_transcript(self, history: Union[List[HistoryItem], List[str]], transcript_file: str) -> None:
45054502
"""Generate a transcript file from a given history of commands"""
45064503
# Validate the transcript file path to make sure directory exists and write access is available
45074504
transcript_path = os.path.abspath(os.path.expanduser(transcript_file))
45084505
transcript_dir = os.path.dirname(transcript_path)
45094506
if not os.path.isdir(transcript_dir) or not os.access(transcript_dir, os.W_OK):
4510-
self.perror("{!r} is not a directory or you don't have write access".format(transcript_dir))
4507+
self.perror(f"'{transcript_dir}' is not a directory or you don't have write access")
45114508
return
45124509

45134510
commands_run = 0
@@ -4537,10 +4534,10 @@ def _generate_transcript(self, history: Union[List[HistoryItem], List[str]], tra
45374534
history_item = history_item.raw
45384535
for line in history_item.splitlines():
45394536
if first:
4540-
command += '{}{}\n'.format(self.prompt, line)
4537+
command += f"{self.prompt}{line}\n"
45414538
first = False
45424539
else:
4543-
command += '{}{}\n'.format(self.continuation_prompt, line)
4540+
command += f"{self.continuation_prompt}{line}\n"
45444541
transcript += command
45454542

45464543
# Use a StdSim object to capture output
@@ -4570,23 +4567,21 @@ def _generate_transcript(self, history: Union[List[HistoryItem], List[str]], tra
45704567

45714568
# Check if all commands ran
45724569
if commands_run < len(history):
4573-
warning = "Command {} triggered a stop and ended transcript generation early".format(commands_run)
4574-
self.pwarning(warning)
4570+
self.pwarning(f"Command {commands_run} triggered a stop and ended transcript generation early")
45754571

45764572
# finally, we can write the transcript out to the file
45774573
try:
4578-
with open(transcript_file, 'w') as fout:
4574+
with open(transcript_path, 'w') as fout:
45794575
fout.write(transcript)
45804576
except OSError as ex:
4581-
self.pexcept('Failed to save transcript: {}'.format(ex))
4577+
self.perror(f"Error saving transcript file '{transcript_path}': {ex}")
45824578
else:
45834579
# and let the user know what we did
45844580
if commands_run > 1:
45854581
plural = 'commands and their outputs'
45864582
else:
45874583
plural = 'command and its output'
4588-
msg = '{} {} saved to transcript file {!r}'
4589-
self.pfeedback(msg.format(commands_run, plural, transcript_file))
4584+
self.pfeedback(f"{commands_run} {plural} saved to transcript file '{transcript_path}'")
45904585

45914586
edit_description = (
45924587
"Run a text editor and optionally open a file with it\n"

cmd2/parsing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ def __init__(
296296
def is_valid_command(self, word: str, *, is_subcommand: bool = False) -> Tuple[bool, str]:
297297
"""Determine whether a word is a valid name for a command.
298298
299-
Commands can not include redirection characters, whitespace,
299+
Commands cannot include redirection characters, whitespace,
300300
or termination characters. They also cannot start with a
301301
shortcut.
302302

docs/api/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ These pages document the public API for ``cmd2``. If a method, class, function,
55
attribute, or constant is not documented here, consider it private and subject
66
to change. There are many classes, methods, functions, and constants in the
77
source code which do not begin with an underscore but are not documented here.
8-
When looking at the source code for this library, you can not safely assume
8+
When looking at the source code for this library, you cannot safely assume
99
that because something doesn't start with an underscore, it is a public API.
1010

1111
If a release of this library changes any of the items documented here, the

docs/features/argument_processing.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ To add additional text to the end of the generated help message, use the ``epilo
170170
from cmd2 import with_argparser
171171

172172
argparser = argparse.ArgumentParser(description='create an html tag',
173-
epilog='This command can not generate tags with no content, like <br/>.')
173+
epilog='This command cannot generate tags with no content, like <br/>.')
174174
argparser.add_argument('tag', help='tag')
175175
argparser.add_argument('content', nargs='+', help='content to surround with tag')
176176
@with_argparser(argparser)
@@ -193,7 +193,7 @@ Which yields:
193193
optional arguments:
194194
-h, --help show this help message and exit
195195
196-
This command can not generate tags with no content, like <br/>
196+
This command cannot generate tags with no content, like <br/>
197197
198198
.. warning::
199199

docs/features/hooks.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ with the :data:`~cmd2.plugin.PostparsingData.stop` attribute set to ``True``:
207207
Precommand Hooks
208208
----------------
209209

210-
Precommand hooks can modify the user input, but can not request the application
210+
Precommand hooks can modify the user input, but cannot request the application
211211
terminate. If your hook needs to be able to exit the application, you should
212212
implement it as a postparsing hook.
213213

tests/test_history.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ def test_history_verbose_with_other_options(base_app):
616616
for opt in options_to_test:
617617
out, err = run_cmd(base_app, 'history -v ' + opt)
618618
assert len(out) == 4
619-
assert out[0] == '-v can not be used with any other options'
619+
assert out[0] == '-v cannot be used with any other options'
620620
assert out[1].startswith('Usage:')
621621

622622

@@ -635,7 +635,7 @@ def test_history_script_with_invalid_options(base_app):
635635
for opt in options_to_test:
636636
out, err = run_cmd(base_app, 'history -s ' + opt)
637637
assert len(out) == 4
638-
assert out[0] == '-s and -x can not be used with -c, -r, -e, -o, or -t'
638+
assert out[0] == '-s and -x cannot be used with -c, -r, -e, -o, or -t'
639639
assert out[1].startswith('Usage:')
640640

641641

@@ -653,7 +653,7 @@ def test_history_expanded_with_invalid_options(base_app):
653653
for opt in options_to_test:
654654
out, err = run_cmd(base_app, 'history -x ' + opt)
655655
assert len(out) == 4
656-
assert out[0] == '-s and -x can not be used with -c, -r, -e, -o, or -t'
656+
assert out[0] == '-s and -x cannot be used with -c, -r, -e, -o, or -t'
657657
assert out[1].startswith('Usage:')
658658

659659

@@ -761,7 +761,7 @@ def test_history_file_permission_error(mocker, capsys):
761761
cmd2.Cmd(persistent_history_file='/tmp/doesntmatter')
762762
out, err = capsys.readouterr()
763763
assert not out
764-
assert 'Can not read' in err
764+
assert 'Cannot read' in err
765765

766766

767767
def test_history_file_conversion_no_truncate_on_init(hist_file, capsys):
@@ -843,4 +843,4 @@ def test_persist_history_permission_error(hist_file, mocker, capsys):
843843
app._persist_history()
844844
out, err = capsys.readouterr()
845845
assert not out
846-
assert 'Can not write' in err
846+
assert 'Cannot write' in err

tests/test_transcript.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,31 +184,24 @@ def test_history_transcript():
184184
assert xscript == expected
185185

186186

187-
def test_history_transcript_bad_filename():
187+
def test_history_transcript_bad_path(mocker):
188188
app = CmdLineApp()
189189
app.stdout = StdSim(app.stdout)
190190
run_cmd(app, 'orate this is\na /multiline/\ncommand;\n')
191191
run_cmd(app, 'speak /tmp/file.txt is not a regex')
192192

193-
expected = r"""(Cmd) orate this is
194-
> a /multiline/
195-
> command;
196-
this is a \/multiline\/ command
197-
(Cmd) speak /tmp/file.txt is not a regex
198-
\/tmp\/file.txt is not a regex
199-
"""
200-
201-
# make a tmp file
193+
# Bad directory
202194
history_fname = '~/fakedir/this_does_not_exist.txt'
195+
out, err = run_cmd(app, 'history -t "{}"'.format(history_fname))
196+
assert "is not a directory" in err[0]
203197

204-
# tell the history command to create a transcript
205-
run_cmd(app, 'history -t "{}"'.format(history_fname))
198+
# Cause os.open to fail and make sure error gets printed
199+
mock_remove = mocker.patch('builtins.open')
200+
mock_remove.side_effect = OSError
206201

207-
# read in the transcript created by the history command
208-
with pytest.raises(FileNotFoundError):
209-
with open(history_fname) as f:
210-
transcript = f.read()
211-
assert transcript == expected
202+
history_fname = 'outfile.txt'
203+
out, err = run_cmd(app, 'history -t "{}"'.format(history_fname))
204+
assert "Error saving transcript file" in err[0]
212205

213206

214207
def test_run_script_record_transcript(base_app, request):

tests_isolated/test_commandset/test_commandset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def test_custom_construct_commandsets():
157157
cmds_cats, cmds_doc, cmds_undoc, help_topics = app._build_command_info()
158158
assert 'Command Set B' in cmds_cats
159159

160-
# Verifies that the same CommandSet can not be loaded twice
160+
# Verifies that the same CommandSet cannot be loaded twice
161161
command_set_2 = CommandSetB('bar')
162162
with pytest.raises(CommandSetRegistrationError):
163163
assert app.register_command_set(command_set_2)

0 commit comments

Comments
 (0)