These files are a subset of the python-2.7.2.tgz distribution from python.org. Changed files from PyMod-2.7.2 have been copied into the corresponding directories of this tree, replacing the original files in the distribution. Signed-off-by: daryl.mcdaniel@intel.com git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13197 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			169 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| r"""Utilities to compile possibly incomplete Python source code.
 | |
| 
 | |
| This module provides two interfaces, broadly similar to the builtin
 | |
| function compile(), which take program text, a filename and a 'mode'
 | |
| and:
 | |
| 
 | |
| - Return 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).
 | |
| 
 | |
| Approach:
 | |
| 
 | |
| 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.
 | |
| 
 | |
| 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.
 | |
| 
 | |
| Caveat:
 | |
| 
 | |
| 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.
 | |
| 
 | |
| The two interfaces are:
 | |
| 
 | |
| compile_command(source, filename, symbol):
 | |
| 
 | |
|     Compiles a single command in the manner described above.
 | |
| 
 | |
| 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"]
 | |
| 
 | |
| PyCF_DONT_IMPLY_DEDENT = 0x200          # Matches pythonrun.h
 | |
| 
 | |
| 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()
 | |
|         if line and line[0] != '#':
 | |
|             break               # Leave it alone
 | |
|     else:
 | |
|         if symbol != "eval":
 | |
|             source = "pass"     # Replace it with a 'pass' statement
 | |
| 
 | |
|     err = err1 = err2 = None
 | |
|     code = code1 = code2 = None
 | |
| 
 | |
|     try:
 | |
|         code = compiler(source, filename, symbol)
 | |
|     except SyntaxError, err:
 | |
|         pass
 | |
| 
 | |
|     try:
 | |
|         code1 = compiler(source + "\n", filename, symbol)
 | |
|     except SyntaxError, err1:
 | |
|         pass
 | |
| 
 | |
|     try:
 | |
|         code2 = compiler(source + "\n\n", filename, symbol)
 | |
|     except SyntaxError, err2:
 | |
|         pass
 | |
| 
 | |
|     if code:
 | |
|         return code
 | |
|     if not code1 and repr(err1) == repr(err2):
 | |
|         raise SyntaxError, err1
 | |
| 
 | |
| def _compile(source, filename, symbol):
 | |
|     return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
 | |
| 
 | |
| 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 = PyCF_DONT_IMPLY_DEDENT
 | |
| 
 | |
|     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)
 |