| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | r"""Utilities to compile possibly incomplete Python source code.
 | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | This module provides two interfaces, broadly similar to the builtin | 
					
						
							|  |  |  | function compile(), that take progam text, a filename and a 'mode' | 
					
						
							|  |  |  | and: | 
					
						
							| 
									
										
										
										
											2001-01-20 19:54:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | - 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). | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | Approach: | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | 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. | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | 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. | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | Caveat: | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | 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. | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | The two interfaces are: | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | compile_command(source, filename, symbol): | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  |     Compiles a single command in the manner described above. | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | CommandCompiler(): | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  |     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"] | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | def _maybe_compile(compiler, source, filename, symbol): | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  |     # Check for source consisting of only blank lines and comments | 
					
						
							| 
									
										
										
										
											2001-02-09 08:56:30 +00:00
										 |  |  |     for line in source.split("\n"): | 
					
						
							|  |  |  |         line = line.strip() | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  |         if line and line[0] != '#': | 
					
						
							|  |  |  |             break               # Leave it alone | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         source = "pass"         # Replace it with a 'pass' statement | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     err = err1 = err2 = None | 
					
						
							|  |  |  |     code = code1 = code2 = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  |         code = compiler(source, filename, symbol) | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  |     except SyntaxError, err: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  |         code1 = compiler(source + "\n", filename, symbol) | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  |     except SyntaxError, err1: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  |         code2 = compiler(source + "\n\n", filename, symbol) | 
					
						
							| 
									
										
										
										
											1998-10-22 21:56:15 +00:00
										 |  |  |     except SyntaxError, err2: | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if code: | 
					
						
							|  |  |  |         return code | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         e1 = err1.__dict__ | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  |         e1 = err1 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         e2 = err2.__dict__ | 
					
						
							|  |  |  |     except AttributeError: | 
					
						
							|  |  |  |         e2 = err2 | 
					
						
							|  |  |  |     if not code1 and e1 == e2: | 
					
						
							|  |  |  |         raise SyntaxError, err1 | 
					
						
							| 
									
										
										
										
											2001-08-17 22:11:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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) |