@@ -2957,161 +2957,170 @@ def do_py(self, args: argparse.Namespace) -> bool:
29572957 self .perror (err , traceback_war = False )
29582958 self ._last_result = CommandResult ('' , err )
29592959 return False
2960- self ._in_py = True
29612960
2962- # Support the run command even if called prior to invoking an interactive interpreter
2963- def py_run (filename : str ):
2964- """Run a Python script file in the interactive console.
2965- :param filename: filename of *.py script file to run
2966- """
2967- expanded_filename = os .path .expanduser (filename )
2961+ try :
2962+ self ._in_py = True
29682963
2969- # cmd_echo defaults to False for scripts. The user can always toggle this value in their script.
2970- bridge .cmd_echo = False
2964+ # Support the run command even if called prior to invoking an interactive interpreter
2965+ def py_run (filename : str ):
2966+ """Run a Python script file in the interactive console.
2967+ :param filename: filename of *.py script file to run
2968+ """
2969+ expanded_filename = os .path .expanduser (filename )
29712970
2972- try :
2973- with open (expanded_filename ) as f :
2974- interp .runcode (f .read ())
2975- except OSError as ex :
2976- error_msg = "Error opening script file '{}': {}" .format (expanded_filename , ex )
2977- self .perror (error_msg , traceback_war = False )
2978-
2979- def py_quit ():
2980- """Function callable from the interactive Python console to exit that environment"""
2981- raise EmbeddedConsoleExit
2982-
2983- # Set up Python environment
2984- bridge = PyscriptBridge (self )
2985- self .pystate [self .pyscript_name ] = bridge
2986- self .pystate ['run' ] = py_run
2987- self .pystate ['quit' ] = py_quit
2988- self .pystate ['exit' ] = py_quit
2989-
2990- if self .locals_in_py :
2991- self .pystate ['self' ] = self
2992- elif 'self' in self .pystate :
2993- del self .pystate ['self' ]
2994-
2995- localvars = self .pystate
2996- from code import InteractiveConsole
2997- interp = InteractiveConsole (locals = localvars )
2998- interp .runcode ('import sys, os;sys.path.insert(0, os.getcwd())' )
2999-
3000- # Check if the user is running a Python statement on the command line
3001- if args .command :
3002- full_command = args .command
3003- if args .remainder :
3004- full_command += ' ' + ' ' .join (args .remainder )
3005-
3006- # Set cmd_echo to True so PyscriptBridge statements like: py app('help')
3007- # run at the command line will print their output.
3008- bridge .cmd_echo = True
3009-
3010- # noinspection PyBroadException
3011- try :
3012- interp .runcode (full_command )
3013- except BaseException :
3014- pass
2971+ # cmd_echo defaults to False for scripts. The user can always toggle this value in their script.
2972+ bridge .cmd_echo = False
30152973
3016- # If there are no args, then we will open an interactive Python console
3017- else :
3018- # Set up readline for Python console
3019- if rl_type != RlType .NONE :
3020- # Save cmd2 history
3021- saved_cmd2_history = []
3022- for i in range (1 , readline .get_current_history_length () + 1 ):
3023- saved_cmd2_history .append (readline .get_history_item (i ))
2974+ try :
2975+ with open (expanded_filename ) as f :
2976+ interp .runcode (f .read ())
2977+ except OSError as ex :
2978+ error_msg = "Error opening script file '{}': {}" .format (expanded_filename , ex )
2979+ self .perror (error_msg , traceback_war = False )
30242980
3025- readline .clear_history ()
2981+ def py_quit ():
2982+ """Function callable from the interactive Python console to exit that environment"""
2983+ raise EmbeddedConsoleExit
30262984
3027- # Restore py's history
3028- for item in self .py_history :
3029- readline .add_history (item )
3030-
3031- if self .use_rawinput and self .completekey :
3032- # Set up tab completion for the Python console
3033- # rlcompleter relies on the default settings of the Python readline module
3034- if rl_type == RlType .GNU :
3035- old_basic_quotes = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
3036- rl_basic_quote_characters .value = orig_rl_basic_quotes
3037-
3038- if 'gnureadline' in sys .modules :
3039- # rlcompleter imports readline by name, so it won't use gnureadline
3040- # Force rlcompleter to use gnureadline instead so it has our settings and history
3041- saved_readline = None
3042- if 'readline' in sys .modules :
3043- saved_readline = sys .modules ['readline' ]
3044-
3045- sys .modules ['readline' ] = sys .modules ['gnureadline' ]
3046-
3047- old_delims = readline .get_completer_delims ()
3048- readline .set_completer_delims (orig_rl_delims )
3049-
3050- # rlcompleter will not need cmd2's custom display function
3051- # This will be restored by cmd2 the next time complete() is called
3052- if rl_type == RlType .GNU :
3053- readline .set_completion_display_matches_hook (None )
3054- elif rl_type == RlType .PYREADLINE :
3055- readline .rl .mode ._display_completions = self ._display_matches_pyreadline
3056-
3057- # Save off the current completer and set a new one in the Python console
3058- # Make sure it tab completes from its locals() dictionary
3059- old_completer = readline .get_completer ()
3060- interp .runcode ("from rlcompleter import Completer" )
3061- interp .runcode ("import readline" )
3062- interp .runcode ("readline.set_completer(Completer(locals()).complete)" )
3063-
3064- # Set up sys module for the Python console
3065- self ._reset_py_display ()
3066- keepstate = Statekeeper (sys , ('stdin' , 'stdout' ))
3067- sys .stdout = self .stdout
3068- sys .stdin = self .stdin
3069-
3070- cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
3071- instructions = ('End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()`.\n '
3072- 'Non-Python commands can be issued with: {}("your command")\n '
3073- 'Run Python code from external script files with: run("script.py")'
3074- .format (self .pyscript_name ))
3075-
3076- # noinspection PyBroadException
3077- try :
3078- interp .interact (banner = "Python {} on {}\n {}\n \n {}\n " .
3079- format (sys .version , sys .platform , cprt , instructions ))
3080- except BaseException :
3081- pass
2985+ # Set up Python environment
2986+ bridge = PyscriptBridge (self )
2987+ self .pystate [self .pyscript_name ] = bridge
2988+ self .pystate ['run' ] = py_run
2989+ self .pystate ['quit' ] = py_quit
2990+ self .pystate ['exit' ] = py_quit
30822991
3083- finally :
3084- keepstate .restore ()
2992+ if self .locals_in_py :
2993+ self .pystate ['self' ] = self
2994+ elif 'self' in self .pystate :
2995+ del self .pystate ['self' ]
2996+
2997+ localvars = self .pystate
2998+ from code import InteractiveConsole
2999+ interp = InteractiveConsole (locals = localvars )
3000+ interp .runcode ('import sys, os;sys.path.insert(0, os.getcwd())' )
3001+
3002+ # Check if the user is running a Python statement on the command line
3003+ if args .command :
3004+ full_command = args .command
3005+ if args .remainder :
3006+ full_command += ' ' + ' ' .join (args .remainder )
3007+
3008+ # Set cmd_echo to True so PyscriptBridge statements like: py app('help')
3009+ # run at the command line will print their output.
3010+ bridge .cmd_echo = True
3011+
3012+ # noinspection PyBroadException
3013+ try :
3014+ interp .runcode (full_command )
3015+ except BaseException :
3016+ # We don't care about any exception that happened in the interactive console
3017+ pass
30853018
3086- # Set up readline for cmd2
3019+ # If there are no args, then we will open an interactive Python console
3020+ else :
3021+ # Set up readline for Python console
30873022 if rl_type != RlType .NONE :
3088- # Save py's history
3089- self . py_history . clear ()
3023+ # Save cmd2 history
3024+ saved_cmd2_history = []
30903025 for i in range (1 , readline .get_current_history_length () + 1 ):
3091- self . py_history .append (readline .get_history_item (i ))
3026+ saved_cmd2_history .append (readline .get_history_item (i ))
30923027
30933028 readline .clear_history ()
30943029
3095- # Restore cmd2 's history
3096- for item in saved_cmd2_history :
3030+ # Restore py 's history
3031+ for item in self . py_history :
30973032 readline .add_history (item )
30983033
30993034 if self .use_rawinput and self .completekey :
3100- # Restore cmd2's tab completion settings
3101- readline .set_completer (old_completer )
3102- readline .set_completer_delims (old_delims )
3103-
3035+ # Set up tab completion for the Python console
3036+ # rlcompleter relies on the default settings of the Python readline module
31043037 if rl_type == RlType .GNU :
3105- rl_basic_quote_characters .value = old_basic_quotes
3038+ old_basic_quotes = ctypes .cast (rl_basic_quote_characters , ctypes .c_void_p ).value
3039+ rl_basic_quote_characters .value = orig_rl_basic_quotes
31063040
31073041 if 'gnureadline' in sys .modules :
3108- # Restore what the readline module pointed to
3109- if saved_readline is None :
3110- del (sys .modules ['readline' ])
3111- else :
3112- sys .modules ['readline' ] = saved_readline
3042+ # rlcompleter imports readline by name, so it won't use gnureadline
3043+ # Force rlcompleter to use gnureadline instead so it has our settings and history
3044+ saved_readline = None
3045+ if 'readline' in sys .modules :
3046+ saved_readline = sys .modules ['readline' ]
3047+
3048+ sys .modules ['readline' ] = sys .modules ['gnureadline' ]
3049+
3050+ old_delims = readline .get_completer_delims ()
3051+ readline .set_completer_delims (orig_rl_delims )
3052+
3053+ # rlcompleter will not need cmd2's custom display function
3054+ # This will be restored by cmd2 the next time complete() is called
3055+ if rl_type == RlType .GNU :
3056+ readline .set_completion_display_matches_hook (None )
3057+ elif rl_type == RlType .PYREADLINE :
3058+ readline .rl .mode ._display_completions = self ._display_matches_pyreadline
3059+
3060+ # Save off the current completer and set a new one in the Python console
3061+ # Make sure it tab completes from its locals() dictionary
3062+ old_completer = readline .get_completer ()
3063+ interp .runcode ("from rlcompleter import Completer" )
3064+ interp .runcode ("import readline" )
3065+ interp .runcode ("readline.set_completer(Completer(locals()).complete)" )
3066+
3067+ # Set up sys module for the Python console
3068+ self ._reset_py_display ()
3069+ keepstate = Statekeeper (sys , ('stdin' , 'stdout' ))
3070+ sys .stdout = self .stdout
3071+ sys .stdin = self .stdin
3072+
3073+ cprt = 'Type "help", "copyright", "credits" or "license" for more information.'
3074+ instructions = ('End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()`.\n '
3075+ 'Non-Python commands can be issued with: {}("your command")\n '
3076+ 'Run Python code from external script files with: run("script.py")'
3077+ .format (self .pyscript_name ))
3078+
3079+ # noinspection PyBroadException
3080+ try :
3081+ interp .interact (banner = "Python {} on {}\n {}\n \n {}\n " .
3082+ format (sys .version , sys .platform , cprt , instructions ))
3083+ except BaseException :
3084+ # We don't care about any exception that happened in the interactive console
3085+ pass
3086+
3087+ finally :
3088+ keepstate .restore ()
3089+
3090+ # Set up readline for cmd2
3091+ if rl_type != RlType .NONE :
3092+ # Save py's history
3093+ self .py_history .clear ()
3094+ for i in range (1 , readline .get_current_history_length () + 1 ):
3095+ self .py_history .append (readline .get_history_item (i ))
3096+
3097+ readline .clear_history ()
3098+
3099+ # Restore cmd2's history
3100+ for item in saved_cmd2_history :
3101+ readline .add_history (item )
3102+
3103+ if self .use_rawinput and self .completekey :
3104+ # Restore cmd2's tab completion settings
3105+ readline .set_completer (old_completer )
3106+ readline .set_completer_delims (old_delims )
3107+
3108+ if rl_type == RlType .GNU :
3109+ rl_basic_quote_characters .value = old_basic_quotes
3110+
3111+ if 'gnureadline' in sys .modules :
3112+ # Restore what the readline module pointed to
3113+ if saved_readline is None :
3114+ del (sys .modules ['readline' ])
3115+ else :
3116+ sys .modules ['readline' ] = saved_readline
3117+
3118+ except KeyboardInterrupt :
3119+ pass
3120+
3121+ finally :
3122+ self ._in_py = False
31133123
3114- self ._in_py = False
31153124 return self ._should_quit
31163125
31173126 pyscript_parser = ACArgumentParser ()
@@ -3125,18 +3134,25 @@ def py_quit():
31253134 def do_pyscript (self , args : argparse .Namespace ) -> bool :
31263135 """Run a Python script file inside the console"""
31273136 script_path = os .path .expanduser (args .script_path )
3137+ py_return = False
31283138
31293139 # Save current command line arguments
31303140 orig_args = sys .argv
31313141
3132- # Overwrite sys.argv to allow the script to take command line arguments
3133- sys .argv = [script_path ] + args .script_arguments
3142+ try :
3143+ # Overwrite sys.argv to allow the script to take command line arguments
3144+ sys .argv = [script_path ] + args .script_arguments
31343145
3135- # Run the script - use repr formatting to escape things which need to be escaped to prevent issues on Windows
3136- py_return = self .do_py ("run({!r})" .format (script_path ))
3146+ # Run the script - use repr formatting to escape things which
3147+ # need to be escaped to prevent issues on Windows
3148+ py_return = self .do_py ("run({!r})" .format (script_path ))
31373149
3138- # Restore command line arguments to original state
3139- sys .argv = orig_args
3150+ except KeyboardInterrupt :
3151+ pass
3152+
3153+ finally :
3154+ # Restore command line arguments to original state
3155+ sys .argv = orig_args
31403156
31413157 return py_return
31423158
0 commit comments