mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	A fiddled version of the rest of Michael Hudson's SF patch
#449043 supporting __future__ in simulated shells which implements PEP 264.
This commit is contained in:
		
							parent
							
								
									10d7255249
								
							
						
					
					
						commit
						6cd6a82db9
					
				
					 4 changed files with 157 additions and 47 deletions
				
			
		
							
								
								
									
										158
									
								
								Lib/codeop.py
									
										
									
									
									
								
							
							
						
						
									
										158
									
								
								Lib/codeop.py
									
										
									
									
									
								
							|  | @ -1,49 +1,69 @@ | |||
| """Utility to compile possibly incomplete Python source code.""" | ||||
| r"""Utilities to compile possibly incomplete Python source code. | ||||
| 
 | ||||
| __all__ = ["compile_command"] | ||||
| This module provides two interfaces, broadly similar to the builtin | ||||
| function compile(), that take progam text, a filename and a 'mode' | ||||
| and: | ||||
| 
 | ||||
| def compile_command(source, filename="<input>", symbol="single"): | ||||
|     r"""Compile a command and determine whether it is incomplete. | ||||
| - Return a code object if the command is complete and valid | ||||
| - Return None if the command is incomplete | ||||
| - Raise SyntaxError, ValueError or OverflowError if the command is a | ||||
|   syntax error (OverflowError and ValueError can be produced by | ||||
|   malformed literals). | ||||
| 
 | ||||
|     Arguments: | ||||
| Approach: | ||||
| 
 | ||||
|     source -- the source string; may contain \n characters | ||||
|     filename -- optional filename from which source was read; default "<input>" | ||||
|     symbol -- optional grammar start symbol; "single" (default) or "eval" | ||||
| First, check if the source consists entirely of blank lines and | ||||
| comments; if so, replace it with 'pass', because the built-in | ||||
| parser doesn't always do the right thing for these. | ||||
| 
 | ||||
|     Return value / exceptions raised: | ||||
| Compile three times: as is, with \n, and with \n\n appended.  If it | ||||
| compiles as is, it's complete.  If it compiles with one \n appended, | ||||
| we expect more.  If it doesn't compile either way, we compare the | ||||
| error we get when compiling with \n or \n\n appended.  If the errors | ||||
| are the same, the code is broken.  But if the errors are different, we | ||||
| expect more.  Not intuitive; not even guaranteed to hold in future | ||||
| releases; but this matches the compiler's behavior from Python 1.4 | ||||
| through 2.2, at least. | ||||
| 
 | ||||
|     - Return a code object if the command is complete and valid | ||||
|     - Return None if the command is incomplete | ||||
|     - Raise SyntaxError or OverflowError if the command is a syntax error | ||||
|       (OverflowError if the error is in a numeric constant) | ||||
| Caveat: | ||||
| 
 | ||||
|     Approach: | ||||
| It is possible (but not likely) that the parser stops parsing with a | ||||
| successful outcome before reaching the end of the source; in this | ||||
| case, trailing symbols may be ignored instead of causing an error. | ||||
| For example, a backslash followed by two newlines may be followed by | ||||
| arbitrary garbage.  This will be fixed once the API for the parser is | ||||
| better. | ||||
| 
 | ||||
|     First, check if the source consists entirely of blank lines and | ||||
|     comments; if so, replace it with 'pass', because the built-in | ||||
|     parser doesn't always do the right thing for these. | ||||
| The two interfaces are: | ||||
| 
 | ||||
|     Compile three times: as is, with \n, and with \n\n appended.  If | ||||
|     it compiles as is, it's complete.  If it compiles with one \n | ||||
|     appended, we expect more.  If it doesn't compile either way, we | ||||
|     compare the error we get when compiling with \n or \n\n appended. | ||||
|     If the errors are the same, the code is broken.  But if the errors | ||||
|     are different, we expect more.  Not intuitive; not even guaranteed | ||||
|     to hold in future releases; but this matches the compiler's | ||||
|     behavior from Python 1.4 through 1.5.2, at least. | ||||
| compile_command(source, filename, symbol): | ||||
| 
 | ||||
|     Caveat: | ||||
|     Compiles a single command in the manner described above. | ||||
| 
 | ||||
|     It is possible (but not likely) that the parser stops parsing | ||||
|     with a successful outcome before reaching the end of the source; | ||||
|     in this case, trailing symbols may be ignored instead of causing an | ||||
|     error.  For example, a backslash followed by two newlines may be | ||||
|     followed by arbitrary garbage.  This will be fixed once the API | ||||
|     for the parser is better. | ||||
| CommandCompiler(): | ||||
| 
 | ||||
|     """ | ||||
|     Instances of this class have __call__ methods identical in | ||||
|     signature to compile_command; the difference is that if the | ||||
|     instance compiles program text containing a __future__ statement, | ||||
|     the instance 'remembers' and compiles all subsequent program texts | ||||
|     with the statement in force. | ||||
| 
 | ||||
| The module also provides another class: | ||||
| 
 | ||||
| Compile(): | ||||
| 
 | ||||
|     Instances of this class act like the built-in function compile, | ||||
|     but with 'memory' in the sense described above. | ||||
| """ | ||||
| 
 | ||||
| import __future__ | ||||
| 
 | ||||
| _features = [getattr(__future__, fname) | ||||
|              for fname in __future__.all_feature_names] | ||||
| 
 | ||||
| __all__ = ["compile_command", "Compile", "CommandCompiler"] | ||||
| 
 | ||||
| def _maybe_compile(compiler, source, filename, symbol): | ||||
|     # Check for source consisting of only blank lines and comments | ||||
|     for line in source.split("\n"): | ||||
|         line = line.strip() | ||||
|  | @ -56,17 +76,17 @@ def compile_command(source, filename="<input>", symbol="single"): | |||
|     code = code1 = code2 = None | ||||
| 
 | ||||
|     try: | ||||
|         code = compile(source, filename, symbol) | ||||
|         code = compiler(source, filename, symbol) | ||||
|     except SyntaxError, err: | ||||
|         pass | ||||
| 
 | ||||
|     try: | ||||
|         code1 = compile(source + "\n", filename, symbol) | ||||
|         code1 = compiler(source + "\n", filename, symbol) | ||||
|     except SyntaxError, err1: | ||||
|         pass | ||||
| 
 | ||||
|     try: | ||||
|         code2 = compile(source + "\n\n", filename, symbol) | ||||
|         code2 = compiler(source + "\n\n", filename, symbol) | ||||
|     except SyntaxError, err2: | ||||
|         pass | ||||
| 
 | ||||
|  | @ -82,3 +102,69 @@ def compile_command(source, filename="<input>", symbol="single"): | |||
|         e2 = err2 | ||||
|     if not code1 and e1 == e2: | ||||
|         raise SyntaxError, err1 | ||||
| 
 | ||||
| def compile_command(source, filename="<input>", symbol="single"): | ||||
|     r"""Compile a command and determine whether it is incomplete. | ||||
| 
 | ||||
|     Arguments: | ||||
| 
 | ||||
|     source -- the source string; may contain \n characters | ||||
|     filename -- optional filename from which source was read; default | ||||
|                 "<input>" | ||||
|     symbol -- optional grammar start symbol; "single" (default) or "eval" | ||||
| 
 | ||||
|     Return value / exceptions raised: | ||||
| 
 | ||||
|     - Return a code object if the command is complete and valid | ||||
|     - Return None if the command is incomplete | ||||
|     - Raise SyntaxError, ValueError or OverflowError if the command is a | ||||
|       syntax error (OverflowError and ValueError can be produced by | ||||
|       malformed literals). | ||||
|     """ | ||||
|     return _maybe_compile(compile, source, filename, symbol) | ||||
| 
 | ||||
| class Compile: | ||||
|     """Instances of this class behave much like the built-in compile | ||||
|     function, but if one is used to compile text containing a future | ||||
|     statement, it "remembers" and compiles all subsequent program texts | ||||
|     with the statement in force.""" | ||||
|     def __init__(self): | ||||
|         self.flags = 0 | ||||
| 
 | ||||
|     def __call__(self, source, filename, symbol): | ||||
|         codeob = compile(source, filename, symbol, self.flags, 1) | ||||
|         for feature in _features: | ||||
|             if codeob.co_flags & feature.compiler_flag: | ||||
|                 self.flags |= feature.compiler_flag | ||||
|         return codeob | ||||
| 
 | ||||
| class CommandCompiler: | ||||
|     """Instances of this class have __call__ methods identical in | ||||
|     signature to compile_command; the difference is that if the | ||||
|     instance compiles program text containing a __future__ statement, | ||||
|     the instance 'remembers' and compiles all subsequent program texts | ||||
|     with the statement in force.""" | ||||
| 
 | ||||
|     def __init__(self,): | ||||
|         self.compiler = Compile() | ||||
| 
 | ||||
|     def __call__(self, source, filename="<input>", symbol="single"): | ||||
|         r"""Compile a command and determine whether it is incomplete. | ||||
| 
 | ||||
|         Arguments: | ||||
| 
 | ||||
|         source -- the source string; may contain \n characters | ||||
|         filename -- optional filename from which source was read; | ||||
|                     default "<input>" | ||||
|         symbol -- optional grammar start symbol; "single" (default) or | ||||
|                   "eval" | ||||
| 
 | ||||
|         Return value / exceptions raised: | ||||
| 
 | ||||
|         - Return a code object if the command is complete and valid | ||||
|         - Return None if the command is incomplete | ||||
|         - Raise SyntaxError, ValueError or OverflowError if the command is a | ||||
|           syntax error (OverflowError and ValueError can be produced by | ||||
|           malformed literals). | ||||
|         """ | ||||
|         return _maybe_compile(self.compiler, source, filename, symbol) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tim Peters
						Tim Peters