@@ -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,13 @@ def remaining_args(opts_plus_args, arg_list):
195196
196197def _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+ if six .PY3 :
200+ editor_path = subprocess .check_output (['which' , editor ], stderr = subprocess .STDOUT , encoding = 'utf-8' ).strip ()
201+ else :
202+ editor_path = subprocess .check_output (['which' , editor ], stderr = subprocess .STDOUT ).strip ()
203+ except subprocess .CalledProcessError :
204+ editor_path = None
205+ return editor_path
201206
202207
203208def strip_quotes (arg ):
@@ -297,7 +302,7 @@ def new_func(instance, arg):
297302 result = func (instance , arg , opts )
298303 return result
299304
300- new_func .__doc__ = '%s\n %s' % (func .__doc__ , option_parser .format_help ())
305+ new_func .__doc__ = '%s%s' % (func .__doc__ + ' \n ' if func . __doc__ else '' , option_parser .format_help ())
301306 return new_func
302307
303308 return option_setup
@@ -746,7 +751,7 @@ def _redirect_output(self, statement):
746751
747752 # NOTE: We couldn't get a real pipe working via subprocess for Python 3.x prior to 3.5.
748753 # 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 .
754+ # And once command is complete we are the temp file as stdin for the shell command to pipe to.
750755 # TODO: Once support for Python 3.x prior to 3.5 is no longer necessary, replace with a real subprocess pipe
751756
752757 # Redirect stdout to a temporary file
@@ -789,8 +794,8 @@ def _restore_output(self, statement):
789794 # Pipe the contents of tempfile to the specified shell command
790795 with open (self ._temp_filename ) as fd :
791796 pipe_proc = subprocess .Popen (shlex .split (statement .parsed .pipeTo ), stdin = fd ,
792- stdout = subprocess .PIPE , stderr = subprocess . PIPE )
793- output , err = pipe_proc .communicate ()
797+ stdout = subprocess .PIPE )
798+ output , _ = pipe_proc .communicate ()
794799
795800 if six .PY3 :
796801 self .stdout .write (output .decode ())
@@ -970,12 +975,8 @@ def do_help(self, arg):
970975 funcname = self ._func_named (arg )
971976 if funcname :
972977 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 :])
978+ # No special behavior needed, delegate to cmd base class do_help()
979+ cmd .Cmd .do_help (self , funcname [3 :])
979980 else :
980981 # Show a menu of what commands help can be gotten for
981982 self ._help_menu ()
@@ -1140,7 +1141,7 @@ def do_shell(self, command):
11401141 """Execute a command as if at the OS prompt.
11411142
11421143 Usage: shell <command> [arguments]"""
1143- proc = subprocess .Popen (command , stdout = self .stdout , stderr = sys . stderr , shell = True )
1144+ proc = subprocess .Popen (command , stdout = self .stdout , shell = True )
11441145 proc .communicate ()
11451146
11461147 def path_complete (self , text , line , begidx , endidx , dir_exe_only = False , dir_only = False ):
@@ -1573,7 +1574,7 @@ def do_save(self, arg):
15731574 try :
15741575 args = self .saveparser .parseString (arg )
15751576 except pyparsing .ParseException :
1576- self .perror ('Could not understand save target %s' % arg )
1577+ self .perror ('Could not understand save target %s' % arg , traceback_war = False )
15771578 raise SyntaxError (self .do_save .__doc__ )
15781579
15791580 # If a filename was supplied then use that, otherwise use a temp file
@@ -1588,21 +1589,20 @@ def do_save(self, arg):
15881589 elif args .idx :
15891590 saveme = self .history [int (args .idx ) - 1 ]
15901591 else :
1591- saveme = ''
15921592 # Wrap in try to deal with case of empty history
15931593 try :
15941594 # Since this save command has already been added to history, need to go one more back for previous
15951595 saveme = self .history [- 2 ]
15961596 except IndexError :
1597- pass
1597+ self .perror ('History is empty, nothing to save.' , traceback_war = False )
1598+ return
15981599 try :
15991600 f = open (os .path .expanduser (fname ), 'w' )
16001601 f .write (saveme )
16011602 f .close ()
16021603 self .pfeedback ('Saved to {}' .format (fname ))
1603- except Exception :
1604- self .perror ('Error saving {}' .format (fname ))
1605- raise
1604+ except Exception as e :
1605+ self .perror ('Saving {!r} - {}' .format (fname , e .strerror ), traceback_war = False )
16061606
16071607 def do__relative_load (self , file_path ):
16081608 """Runs commands in script file that is encoded as either ASCII or UTF-8 text.
0 commit comments