Skip to content

Commit 482e9ce

Browse files
authored
Merge pull request #164 from python-cmd2/tests
Added a bunch of unit tests
2 parents 02f234f + a771f63 commit 482e9ce

3 files changed

Lines changed: 203 additions & 38 deletions

File tree

cmd2.py

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ def exit(self, status=0, msg=None):
150150
151151
We override exit so it doesn't automatically exit the application.
152152
"""
153-
self.values._exit = True
153+
if self.values is not None:
154+
self.values._exit = True
155+
154156
if msg:
155157
print(msg)
156158

@@ -159,10 +161,9 @@ def print_help(self, *args, **kwargs):
159161
160162
We override it so that before the standard optparse help, it prints the do_* method docstring, if available.
161163
"""
162-
try:
164+
if self._func.__doc__:
163165
print(self._func.__doc__)
164-
except AttributeError:
165-
pass
166+
166167
optparse.OptionParser.print_help(self, *args, **kwargs)
167168

168169
def error(self, msg):
@@ -195,9 +196,12 @@ def remaining_args(opts_plus_args, arg_list):
195196

196197
def _which(editor):
197198
try:
198-
return subprocess.Popen(['which', editor], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0]
199-
except OSError:
200-
return None
199+
editor_path = subprocess.check_output(['which', editor], stderr=subprocess.STDOUT).strip()
200+
if six.PY3:
201+
editor_path = editor_path.decode()
202+
except subprocess.CalledProcessError:
203+
editor_path = None
204+
return editor_path
201205

202206

203207
def strip_quotes(arg):
@@ -297,7 +301,7 @@ def new_func(instance, arg):
297301
result = func(instance, arg, opts)
298302
return result
299303

300-
new_func.__doc__ = '%s\n%s' % (func.__doc__, option_parser.format_help())
304+
new_func.__doc__ = '%s%s' % (func.__doc__ + '\n' if func.__doc__ else '', option_parser.format_help())
301305
return new_func
302306

303307
return option_setup
@@ -746,7 +750,7 @@ def _redirect_output(self, statement):
746750

747751
# NOTE: We couldn't get a real pipe working via subprocess for Python 3.x prior to 3.5.
748752
# So to allow compatibility with Python 2.7 and 3.3+ we are redirecting output to a temporary file.
749-
# And once command is complete we are using the "cat" shell command to pipe to whatever.
753+
# And once command is complete we are the temp file as stdin for the shell command to pipe to.
750754
# TODO: Once support for Python 3.x prior to 3.5 is no longer necessary, replace with a real subprocess pipe
751755

752756
# Redirect stdout to a temporary file
@@ -789,8 +793,8 @@ def _restore_output(self, statement):
789793
# Pipe the contents of tempfile to the specified shell command
790794
with open(self._temp_filename) as fd:
791795
pipe_proc = subprocess.Popen(shlex.split(statement.parsed.pipeTo), stdin=fd,
792-
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
793-
output, err = pipe_proc.communicate()
796+
stdout=subprocess.PIPE)
797+
output, _ = pipe_proc.communicate()
794798

795799
if six.PY3:
796800
self.stdout.write(output.decode())
@@ -969,13 +973,8 @@ def do_help(self, arg):
969973
# Getting help for a specific command
970974
funcname = self._func_named(arg)
971975
if funcname:
972-
fn = getattr(self, funcname)
973-
try:
974-
# Use Optparse help for @options commands
975-
fn.optionParser.print_help(file=self.stdout)
976-
except AttributeError:
977-
# No special behavior needed, delegate to cmd base class do_help()
978-
cmd.Cmd.do_help(self, funcname[3:])
976+
# No special behavior needed, delegate to cmd base class do_help()
977+
cmd.Cmd.do_help(self, funcname[3:])
979978
else:
980979
# Show a menu of what commands help can be gotten for
981980
self._help_menu()
@@ -1140,7 +1139,7 @@ def do_shell(self, command):
11401139
"""Execute a command as if at the OS prompt.
11411140
11421141
Usage: shell <command> [arguments]"""
1143-
proc = subprocess.Popen(command, stdout=self.stdout, stderr=sys.stderr, shell=True)
1142+
proc = subprocess.Popen(command, stdout=self.stdout, shell=True)
11441143
proc.communicate()
11451144

11461145
def path_complete(self, text, line, begidx, endidx, dir_exe_only=False, dir_only=False):
@@ -1573,7 +1572,7 @@ def do_save(self, arg):
15731572
try:
15741573
args = self.saveparser.parseString(arg)
15751574
except pyparsing.ParseException:
1576-
self.perror('Could not understand save target %s' % arg)
1575+
self.perror('Could not understand save target %s' % arg, traceback_war=False)
15771576
raise SyntaxError(self.do_save.__doc__)
15781577

15791578
# If a filename was supplied then use that, otherwise use a temp file
@@ -1588,21 +1587,20 @@ def do_save(self, arg):
15881587
elif args.idx:
15891588
saveme = self.history[int(args.idx) - 1]
15901589
else:
1591-
saveme = ''
15921590
# Wrap in try to deal with case of empty history
15931591
try:
15941592
# Since this save command has already been added to history, need to go one more back for previous
15951593
saveme = self.history[-2]
15961594
except IndexError:
1597-
pass
1595+
self.perror('History is empty, nothing to save.', traceback_war=False)
1596+
return
15981597
try:
15991598
f = open(os.path.expanduser(fname), 'w')
16001599
f.write(saveme)
16011600
f.close()
16021601
self.pfeedback('Saved to {}'.format(fname))
1603-
except Exception:
1604-
self.perror('Error saving {}'.format(fname))
1605-
raise
1602+
except Exception as e:
1603+
self.perror('Saving {!r} - {}'.format(fname, e), traceback_war=False)
16061604

16071605
def do__relative_load(self, file_path):
16081606
"""Runs commands in script file that is encoded as either ASCII or UTF-8 text.

0 commit comments

Comments
 (0)