Home | History | Annotate | Download | only in Lib
      1 r"""Utilities to compile possibly incomplete Python source code.
      2 
      3 This module provides two interfaces, broadly similar to the builtin
      4 function compile(), which take program text, a filename and a 'mode'
      5 and:
      6 
      7 - Return code object if the command is complete and valid
      8 - Return None if the command is incomplete
      9 - Raise SyntaxError, ValueError or OverflowError if the command is a
     10   syntax error (OverflowError and ValueError can be produced by
     11   malformed literals).
     12 
     13 Approach:
     14 
     15 First, check if the source consists entirely of blank lines and
     16 comments; if so, replace it with 'pass', because the built-in
     17 parser doesn't always do the right thing for these.
     18 
     19 Compile three times: as is, with \n, and with \n\n appended.  If it
     20 compiles as is, it's complete.  If it compiles with one \n appended,
     21 we expect more.  If it doesn't compile either way, we compare the
     22 error we get when compiling with \n or \n\n appended.  If the errors
     23 are the same, the code is broken.  But if the errors are different, we
     24 expect more.  Not intuitive; not even guaranteed to hold in future
     25 releases; but this matches the compiler's behavior from Python 1.4
     26 through 2.2, at least.
     27 
     28 Caveat:
     29 
     30 It is possible (but not likely) that the parser stops parsing with a
     31 successful outcome before reaching the end of the source; in this
     32 case, trailing symbols may be ignored instead of causing an error.
     33 For example, a backslash followed by two newlines may be followed by
     34 arbitrary garbage.  This will be fixed once the API for the parser is
     35 better.
     36 
     37 The two interfaces are:
     38 
     39 compile_command(source, filename, symbol):
     40 
     41     Compiles a single command in the manner described above.
     42 
     43 CommandCompiler():
     44 
     45     Instances of this class have __call__ methods identical in
     46     signature to compile_command; the difference is that if the
     47     instance compiles program text containing a __future__ statement,
     48     the instance 'remembers' and compiles all subsequent program texts
     49     with the statement in force.
     50 
     51 The module also provides another class:
     52 
     53 Compile():
     54 
     55     Instances of this class act like the built-in function compile,
     56     but with 'memory' in the sense described above.
     57 """
     58 
     59 import __future__
     60 
     61 _features = [getattr(__future__, fname)
     62              for fname in __future__.all_feature_names]
     63 
     64 __all__ = ["compile_command", "Compile", "CommandCompiler"]
     65 
     66 PyCF_DONT_IMPLY_DEDENT = 0x200          # Matches pythonrun.h
     67 
     68 def _maybe_compile(compiler, source, filename, symbol):
     69     # Check for source consisting of only blank lines and comments
     70     for line in source.split("\n"):
     71         line = line.strip()
     72         if line and line[0] != '#':
     73             break               # Leave it alone
     74     else:
     75         if symbol != "eval":
     76             source = "pass"     # Replace it with a 'pass' statement
     77 
     78     err = err1 = err2 = None
     79     code = code1 = code2 = None
     80 
     81     try:
     82         code = compiler(source, filename, symbol)
     83     except SyntaxError as err:
     84         pass
     85 
     86     try:
     87         code1 = compiler(source + "\n", filename, symbol)
     88     except SyntaxError as e:
     89         err1 = e
     90 
     91     try:
     92         code2 = compiler(source + "\n\n", filename, symbol)
     93     except SyntaxError as e:
     94         err2 = e
     95 
     96     if code:
     97         return code
     98     if not code1 and repr(err1) == repr(err2):
     99         raise err1
    100 
    101 def _compile(source, filename, symbol):
    102     return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
    103 
    104 def compile_command(source, filename="<input>", symbol="single"):
    105     r"""Compile a command and determine whether it is incomplete.
    106 
    107     Arguments:
    108 
    109     source -- the source string; may contain \n characters
    110     filename -- optional filename from which source was read; default
    111                 "<input>"
    112     symbol -- optional grammar start symbol; "single" (default) or "eval"
    113 
    114     Return value / exceptions raised:
    115 
    116     - Return a code object if the command is complete and valid
    117     - Return None if the command is incomplete
    118     - Raise SyntaxError, ValueError or OverflowError if the command is a
    119       syntax error (OverflowError and ValueError can be produced by
    120       malformed literals).
    121     """
    122     return _maybe_compile(_compile, source, filename, symbol)
    123 
    124 class Compile:
    125     """Instances of this class behave much like the built-in compile
    126     function, but if one is used to compile text containing a future
    127     statement, it "remembers" and compiles all subsequent program texts
    128     with the statement in force."""
    129     def __init__(self):
    130         self.flags = PyCF_DONT_IMPLY_DEDENT
    131 
    132     def __call__(self, source, filename, symbol):
    133         codeob = compile(source, filename, symbol, self.flags, 1)
    134         for feature in _features:
    135             if codeob.co_flags & feature.compiler_flag:
    136                 self.flags |= feature.compiler_flag
    137         return codeob
    138 
    139 class CommandCompiler:
    140     """Instances of this class have __call__ methods identical in
    141     signature to compile_command; the difference is that if the
    142     instance compiles program text containing a __future__ statement,
    143     the instance 'remembers' and compiles all subsequent program texts
    144     with the statement in force."""
    145 
    146     def __init__(self,):
    147         self.compiler = Compile()
    148 
    149     def __call__(self, source, filename="<input>", symbol="single"):
    150         r"""Compile a command and determine whether it is incomplete.
    151 
    152         Arguments:
    153 
    154         source -- the source string; may contain \n characters
    155         filename -- optional filename from which source was read;
    156                     default "<input>"
    157         symbol -- optional grammar start symbol; "single" (default) or
    158                   "eval"
    159 
    160         Return value / exceptions raised:
    161 
    162         - Return a code object if the command is complete and valid
    163         - Return None if the command is incomplete
    164         - Raise SyntaxError, ValueError or OverflowError if the command is a
    165           syntax error (OverflowError and ValueError can be produced by
    166           malformed literals).
    167         """
    168         return _maybe_compile(self.compiler, source, filename, symbol)
    169