1010 syntax error (OverflowError and ValueError can be produced by
1111 malformed literals).
1212
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-
3713The two interfaces are:
3814
3915compile_command(source, filename, symbol):
6440
6541__all__ = ["compile_command", "Compile", "CommandCompiler"]
6642
67- PyCF_DONT_IMPLY_DEDENT = 0x200 # Matches pythonrun.h.
43+ # The following flags match the values from Include/cpython/compile.h
44+ # Caveat emptor: These flags are undocumented on purpose and depending
45+ # on their effect outside the standard library is **unsupported**.
46+ PyCF_DONT_IMPLY_DEDENT = 0x200
47+ PyCF_ALLOW_INCOMPLETE_INPUT = 0x4000
6848
6949def _maybe_compile(compiler, source, filename, symbol):
7050 # Check for source consisting of only blank lines and comments.
@@ -86,24 +66,12 @@ def _maybe_compile(compiler, source, filename, symbol):
8666 with warnings.catch_warnings():
8767 warnings.simplefilter("error")
8868
89- code1 = err1 = err2 = None
90- try:
91- code1 = compiler(source + "\n", filename, symbol)
92- except SyntaxError as e:
93- err1 = e
94-
9569 try:
96- code2 = compiler(source + "\n \n", filename, symbol)
70+ compiler(source + "\n", filename, symbol)
9771 except SyntaxError as e:
98- err2 = e
99-
100- try:
101- if not code1 and _is_syntax_error(err1, err2):
102- raise err1
103- else:
104- return None
105- finally:
106- err1 = err2 = None
72+ if "incomplete input" in str(e):
73+ return None
74+ raise
10775
10876def _is_syntax_error(err1, err2):
10977 rep1 = repr(err1)
@@ -115,7 +83,7 @@ def _is_syntax_error(err1, err2):
11583 return False
11684
11785def _compile(source, filename, symbol):
118- return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT)
86+ return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT )
11987
12088def compile_command(source, filename="<input>", symbol="single"):
12189 r"""Compile a command and determine whether it is incomplete.
@@ -144,7 +112,7 @@ class Compile:
144112 statement, it "remembers" and compiles all subsequent program texts
145113 with the statement in force."""
146114 def __init__(self):
147- self.flags = PyCF_DONT_IMPLY_DEDENT
115+ self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
148116
149117 def __call__(self, source, filename, symbol):
150118 codeob = compile(source, filename, symbol, self.flags, True)
0 commit comments