mirror of
				https://github.com/python/cpython.git
				synced 2025-10-26 19:24:34 +00:00 
			
		
		
		
	Subsume the interact() function in a class. This should make it
possible to use this in PythonWin, and to replace Fredrik Lundh's PythonInterpreter class. Fredrik is credited with the class' API.
This commit is contained in:
		
							parent
							
								
									d9d2625dbd
								
							
						
					
					
						commit
						a93b848e33
					
				
					 1 changed files with 198 additions and 43 deletions
				
			
		
							
								
								
									
										233
									
								
								Lib/code.py
									
										
									
									
									
								
							
							
						
						
									
										233
									
								
								Lib/code.py
									
										
									
									
									
								
							|  | @ -1,5 +1,9 @@ | ||||||
| """Utilities dealing with code objects.""" | """Utilities dealing with code objects.""" | ||||||
| 
 | 
 | ||||||
|  | import sys | ||||||
|  | import string | ||||||
|  | import traceback | ||||||
|  | 
 | ||||||
| def compile_command(source, filename="<input>", symbol="single"): | def compile_command(source, filename="<input>", symbol="single"): | ||||||
|     r"""Compile a command and determine whether it is incomplete. |     r"""Compile a command and determine whether it is incomplete. | ||||||
| 
 | 
 | ||||||
|  | @ -60,51 +64,202 @@ def compile_command(source, filename="<input>", symbol="single"): | ||||||
|         raise SyntaxError, err1 |         raise SyntaxError, err1 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def interact(banner=None, readfunc=raw_input, local=None): | class InteractiveConsole: | ||||||
|     # Due to Jeff Epler, with changes by Guido: |     """Closely emulate the behavior of the interactive Python interpreter. | ||||||
|  | 
 | ||||||
|  |     After code by Jeff Epler and Fredrik Lundh. | ||||||
|  |     """ | ||||||
|  | 
 | ||||||
|  |     def __init__(self, filename="<console>", locals=None): | ||||||
|  |         """Constructor. | ||||||
|  | 
 | ||||||
|  |         The optional filename argument specifies the (file)name of the | ||||||
|  |         input stream; it will show up in tracebacks.  It defaults to | ||||||
|  |         '<console>'. | ||||||
|  | 
 | ||||||
|  |         """ | ||||||
|  |         self.filename = filename | ||||||
|  |         if locals is None: | ||||||
|  |             locals = {} | ||||||
|  |         self.locals = locals | ||||||
|  |         self.resetbuffer() | ||||||
|  | 
 | ||||||
|  |     def resetbuffer(self): | ||||||
|  |         """Reset the input buffer (but not the variables!).""" | ||||||
|  |         self.buffer = [] | ||||||
|  | 
 | ||||||
|  |     def interact(self, banner=None): | ||||||
|         """Closely emulate the interactive Python console.""" |         """Closely emulate the interactive Python console.""" | ||||||
|     try: import readline # Enable GNU readline if available |         try: | ||||||
|     except: pass |             sys.ps1 | ||||||
|     local = local or {} |         except AttributeError: | ||||||
|     import sys, string, traceback |             sys.ps1 = ">>> " | ||||||
|     sys.ps1 = '>>> ' |         try: | ||||||
|     sys.ps2 = '... ' |             sys.ps2 | ||||||
|     if banner: |         except AttributeError: | ||||||
|         print banner |             sys.ps2 = "... " | ||||||
|  |         if banner is None: | ||||||
|  |             self.write("Python %s on %s\n%s\n(%s)\n" % | ||||||
|  |                        (sys.version, sys.platform, sys.copyright, | ||||||
|  |                         self.__class__.__name__)) | ||||||
|         else: |         else: | ||||||
|         print "Python Interactive Console", sys.version |             self.write("%s\n" % str(banner)) | ||||||
|         print sys.copyright |         more = 0 | ||||||
|     buf = [] |  | ||||||
|         while 1: |         while 1: | ||||||
|         if buf: prompt = sys.ps2 |             try: | ||||||
|         else: prompt = sys.ps1 |                 if more: | ||||||
|         try: line = readfunc(prompt) |                     prompt = sys.ps2 | ||||||
|         except KeyboardInterrupt: |  | ||||||
|             print "\nKeyboardInterrupt" |  | ||||||
|             buf = [] |  | ||||||
|             continue |  | ||||||
|         except EOFError: break |  | ||||||
|         buf.append(line) |  | ||||||
|         try: x = compile_command(string.join(buf, "\n")) |  | ||||||
|         except SyntaxError: |  | ||||||
|             traceback.print_exc(0) |  | ||||||
|             buf = [] |  | ||||||
|             continue |  | ||||||
|         if x == None: continue |  | ||||||
|                 else: |                 else: | ||||||
|             try: exec x in local |                     prompt = sys.ps1 | ||||||
|  |                 try: | ||||||
|  |                     line = self.raw_input(prompt) | ||||||
|  |                 except EOFError: | ||||||
|  |                     self.write("\n") | ||||||
|  |                     break | ||||||
|  |                 else: | ||||||
|  |                     more = self.push(line) | ||||||
|  |             except KeyboardInterrupt: | ||||||
|  |                 self.write("\nKeyboardInterrupt\n") | ||||||
|  |                 self.resetbuffer() | ||||||
|  |                 more = 0 | ||||||
|  | 
 | ||||||
|  |     def push(self, line): | ||||||
|  |         """Push a line to the interpreter. | ||||||
|  | 
 | ||||||
|  |         The line should not have a trailing newline. | ||||||
|  | 
 | ||||||
|  |         One of three things will happen: | ||||||
|  | 
 | ||||||
|  |         1) The input is incorrect; compile_command() raised | ||||||
|  |         SyntaxError.  A syntax traceback will be printed. | ||||||
|  | 
 | ||||||
|  |         2) The input is incomplete, and more input is required; | ||||||
|  |         compile_command() returned None. | ||||||
|  | 
 | ||||||
|  |         3) The input is complete; compile_command() returned a code | ||||||
|  |         object.  The code is executed.  When an exception occurs, a | ||||||
|  |         traceback is printed.  All exceptions are caught except | ||||||
|  |         SystemExit, which is reraised. | ||||||
|  | 
 | ||||||
|  |         The return value is 1 in case 2, 0 in the other cases.  (The | ||||||
|  |         return value can be used to decide whether to use sys.ps1 or | ||||||
|  |         sys.ps2 to prompt the next line.) | ||||||
|  | 
 | ||||||
|  |         A note about KeyboardInterrupt: this exception may occur | ||||||
|  |         elsewhere in this code, and will not always be caught.  The | ||||||
|  |         caller should be prepared to deal with it. | ||||||
|  | 
 | ||||||
|  |         """ | ||||||
|  |         self.buffer.append(line) | ||||||
|  | 
 | ||||||
|  |         try: | ||||||
|  |             x = compile_command(string.join(self.buffer, "\n"), | ||||||
|  |                                 filename=self.filename) | ||||||
|  |         except SyntaxError: | ||||||
|  |             # Case 1 | ||||||
|  |             self.showsyntaxerror() | ||||||
|  |             self.resetbuffer() | ||||||
|  |             return 0 | ||||||
|  | 
 | ||||||
|  |         if x is None: | ||||||
|  |             # Case 2 | ||||||
|  |             return 1 | ||||||
|  | 
 | ||||||
|  |         # Case 3 | ||||||
|  |         try: | ||||||
|  |             exec x in self.locals | ||||||
|  |         except SystemExit: | ||||||
|  |             raise | ||||||
|         except: |         except: | ||||||
|                 exc_type, exc_value, exc_traceback = \ |             self.showtraceback() | ||||||
|                         sys.exc_type, sys.exc_value, \ |         self.resetbuffer() | ||||||
|                         sys.exc_traceback |         return 0 | ||||||
|                 l = len(traceback.extract_tb(sys.exc_traceback)) | 
 | ||||||
|                 try: 1/0 |     def showsyntaxerror(self): | ||||||
|  |         """Display the syntax error that just occurred. | ||||||
|  | 
 | ||||||
|  |         This doesn't display a stack trace because there isn't one. | ||||||
|  | 
 | ||||||
|  |         The output is written by self.write(), below. | ||||||
|  | 
 | ||||||
|  |         """ | ||||||
|  |         type, value = sys.exc_info()[:2] | ||||||
|  |         # Work hard to stuff the correct filename in the exception | ||||||
|  |         try: | ||||||
|  |             msg, (filename, lineno, offset, line) = value | ||||||
|         except: |         except: | ||||||
|                     m = len(traceback.extract_tb( |             pass | ||||||
|                             sys.exc_traceback)) |         else: | ||||||
|                 traceback.print_exception(exc_type, |             try: | ||||||
|                         exc_value, exc_traceback, l-m) |                 value = SyntaxError(msg, (self.filename, lineno, offset, line)) | ||||||
|             buf = [] |             except: | ||||||
|  |                 value = msg, (self.filename, lineno, offset, line) | ||||||
|  |         list = traceback.format_exception_only(type, value) | ||||||
|  |         map(self.write, list) | ||||||
|  | 
 | ||||||
|  |     def showtraceback(self): | ||||||
|  |         """Display the exception that just occurred. | ||||||
|  | 
 | ||||||
|  |         We remove the first stack item because it is our own code. | ||||||
|  | 
 | ||||||
|  |         The output is written by self.write(), below. | ||||||
|  | 
 | ||||||
|  |         """ | ||||||
|  |         try: | ||||||
|  |             type, value, tb = sys.exc_info() | ||||||
|  |             tblist = traceback.extract_tb(tb) | ||||||
|  |             del tblist[0] | ||||||
|  |             list = traceback.format_list(tblist) | ||||||
|  |             list[len(list):] = traceback.format_exception_only(type, value) | ||||||
|  |         finally: | ||||||
|  |             tblist = tb = None | ||||||
|  |         map(self.write, list) | ||||||
|  | 
 | ||||||
|  |     def write(self, data): | ||||||
|  |         """Write a string. | ||||||
|  | 
 | ||||||
|  |         The base implementation writes to sys.stderr; a subclass may | ||||||
|  |         replace this with a different implementation. | ||||||
|  | 
 | ||||||
|  |         """ | ||||||
|  |         sys.stderr.write(data) | ||||||
|  | 
 | ||||||
|  |     def raw_input(self, prompt=""): | ||||||
|  |         """Write a prompt and read a line. | ||||||
|  | 
 | ||||||
|  |         The returned line does not include the trailing newline. | ||||||
|  |         When the user enters the EOF key sequence, EOFError is raised. | ||||||
|  | 
 | ||||||
|  |         The base implementation uses the built-in function | ||||||
|  |         raw_input(); a subclass may replace this with a different | ||||||
|  |         implementation. | ||||||
|  | 
 | ||||||
|  |         """ | ||||||
|  |         return raw_input(prompt) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def interact(banner=None, readfunc=None, locals=None): | ||||||
|  |     """Closely emulate the interactive Python interpreter. | ||||||
|  | 
 | ||||||
|  |     This is a backwards compatible interface to the InteractiveConsole | ||||||
|  |     class.  It attempts to import the readline module to enable GNU | ||||||
|  |     readline if it is available. | ||||||
|  | 
 | ||||||
|  |     Arguments (all optional, all default to None): | ||||||
|  | 
 | ||||||
|  |     banner -- passed to InteractiveConsole.interact() | ||||||
|  |     readfunc -- if not None, replaces InteractiveConsole.raw_input() | ||||||
|  |     locals -- passed to InteractiveConsole.__init__() | ||||||
|  | 
 | ||||||
|  |     """ | ||||||
|  |     try: | ||||||
|  |         import readline | ||||||
|  |     except: | ||||||
|  |         pass | ||||||
|  |     console = InteractiveConsole(locals=locals) | ||||||
|  |     if readfunc is not None: | ||||||
|  |         console.raw_input = readfunc | ||||||
|  |     console.interact(banner) | ||||||
|                  |                  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     interact() |     interact() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum