+++ /dev/null
-r"""Utilities to compile possibly incomplete Python source code.\r
-\r
-This module provides two interfaces, broadly similar to the builtin\r
-function compile(), which take program text, a filename and a 'mode'\r
-and:\r
-\r
-- Return code object if the command is complete and valid\r
-- Return None if the command is incomplete\r
-- Raise SyntaxError, ValueError or OverflowError if the command is a\r
- syntax error (OverflowError and ValueError can be produced by\r
- malformed literals).\r
-\r
-Approach:\r
-\r
-First, check if the source consists entirely of blank lines and\r
-comments; if so, replace it with 'pass', because the built-in\r
-parser doesn't always do the right thing for these.\r
-\r
-Compile three times: as is, with \n, and with \n\n appended. If it\r
-compiles as is, it's complete. If it compiles with one \n appended,\r
-we expect more. If it doesn't compile either way, we compare the\r
-error we get when compiling with \n or \n\n appended. If the errors\r
-are the same, the code is broken. But if the errors are different, we\r
-expect more. Not intuitive; not even guaranteed to hold in future\r
-releases; but this matches the compiler's behavior from Python 1.4\r
-through 2.2, at least.\r
-\r
-Caveat:\r
-\r
-It is possible (but not likely) that the parser stops parsing with a\r
-successful outcome before reaching the end of the source; in this\r
-case, trailing symbols may be ignored instead of causing an error.\r
-For example, a backslash followed by two newlines may be followed by\r
-arbitrary garbage. This will be fixed once the API for the parser is\r
-better.\r
-\r
-The two interfaces are:\r
-\r
-compile_command(source, filename, symbol):\r
-\r
- Compiles a single command in the manner described above.\r
-\r
-CommandCompiler():\r
-\r
- Instances of this class have __call__ methods identical in\r
- signature to compile_command; the difference is that if the\r
- instance compiles program text containing a __future__ statement,\r
- the instance 'remembers' and compiles all subsequent program texts\r
- with the statement in force.\r
-\r
-The module also provides another class:\r
-\r
-Compile():\r
-\r
- Instances of this class act like the built-in function compile,\r
- but with 'memory' in the sense described above.\r
-"""\r
-\r
-import __future__\r
-\r
-_features = [getattr(__future__, fname)\r
- for fname in __future__.all_feature_names]\r
-\r
-__all__ = ["compile_command", "Compile", "CommandCompiler"]\r
-\r
-PyCF_DONT_IMPLY_DEDENT = 0x200 # Matches pythonrun.h\r
-\r
-def _maybe_compile(compiler, source, filename, symbol):\r
- # Check for source consisting of only blank lines and comments\r
- for line in source.split("\n"):\r
- line = line.strip()\r
- if line and line[0] != '#':\r
- break # Leave it alone\r
- else:\r
- if symbol != "eval":\r
- source = "pass" # Replace it with a 'pass' statement\r
-\r
- err = err1 = err2 = None\r
- code = code1 = code2 = None\r
-\r
- try:\r
- code = compiler(source, filename, symbol)\r
- except SyntaxError, err:\r
- pass\r
-\r
- try:\r
- code1 = compiler(source + "\n", filename, symbol)\r
- except SyntaxError, err1:\r
- pass\r
-\r
- try:\r
- code2 = compiler(source + "\n\n", filename, symbol)\r
- except SyntaxError, err2:\r
- pass\r
-\r
- if code:\r
- return code\r
- if not code1 and repr(err1) == repr(err2):\r
- raise SyntaxError, err1\r
-\r
-def _compile(source, filename, symbol):\r
- return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)\r
-\r
-def compile_command(source, filename="<input>", symbol="single"):\r
- r"""Compile a command and determine whether it is incomplete.\r
-\r
- Arguments:\r
-\r
- source -- the source string; may contain \n characters\r
- filename -- optional filename from which source was read; default\r
- "<input>"\r
- symbol -- optional grammar start symbol; "single" (default) or "eval"\r
-\r
- Return value / exceptions raised:\r
-\r
- - Return a code object if the command is complete and valid\r
- - Return None if the command is incomplete\r
- - Raise SyntaxError, ValueError or OverflowError if the command is a\r
- syntax error (OverflowError and ValueError can be produced by\r
- malformed literals).\r
- """\r
- return _maybe_compile(_compile, source, filename, symbol)\r
-\r
-class Compile:\r
- """Instances of this class behave much like the built-in compile\r
- function, but if one is used to compile text containing a future\r
- statement, it "remembers" and compiles all subsequent program texts\r
- with the statement in force."""\r
- def __init__(self):\r
- self.flags = PyCF_DONT_IMPLY_DEDENT\r
-\r
- def __call__(self, source, filename, symbol):\r
- codeob = compile(source, filename, symbol, self.flags, 1)\r
- for feature in _features:\r
- if codeob.co_flags & feature.compiler_flag:\r
- self.flags |= feature.compiler_flag\r
- return codeob\r
-\r
-class CommandCompiler:\r
- """Instances of this class have __call__ methods identical in\r
- signature to compile_command; the difference is that if the\r
- instance compiles program text containing a __future__ statement,\r
- the instance 'remembers' and compiles all subsequent program texts\r
- with the statement in force."""\r
-\r
- def __init__(self,):\r
- self.compiler = Compile()\r
-\r
- def __call__(self, source, filename="<input>", symbol="single"):\r
- r"""Compile a command and determine whether it is incomplete.\r
-\r
- Arguments:\r
-\r
- source -- the source string; may contain \n characters\r
- filename -- optional filename from which source was read;\r
- default "<input>"\r
- symbol -- optional grammar start symbol; "single" (default) or\r
- "eval"\r
-\r
- Return value / exceptions raised:\r
-\r
- - Return a code object if the command is complete and valid\r
- - Return None if the command is incomplete\r
- - Raise SyntaxError, ValueError or OverflowError if the command is a\r
- syntax error (OverflowError and ValueError can be produced by\r
- malformed literals).\r
- """\r
- return _maybe_compile(self.compiler, source, filename, symbol)\r