|
1 | | -"""Utilities dealing with code objects. |
| 1 | +"""Utilities needed to emulate Python's interactive interpreter. |
2 | 2 |
|
3 | 3 | Inspired by similar code by Jeff Epler and Fredrik Lundh. |
4 | 4 | """ |
5 | 5 |
|
| 6 | + |
6 | 7 | import sys |
7 | 8 | import string |
8 | 9 | import traceback |
9 | | - |
10 | | -def compile_command(source, filename="<input>", symbol="single"): |
11 | | - r"""Compile a command and determine whether it is incomplete. |
12 | | -
|
13 | | - Arguments: |
14 | | -
|
15 | | - source -- the source string; may contain \n characters |
16 | | - filename -- optional filename from which source was read; default "<input>" |
17 | | - symbol -- optional grammar start symbol; "single" (default) or "eval" |
18 | | -
|
19 | | - Return value / exceptions raised: |
20 | | -
|
21 | | - - Return a code object if the command is complete and valid |
22 | | - - Return None if the command is incomplete |
23 | | - - Raise SyntaxError or OverflowError if the command is a syntax error |
24 | | - (OverflowError if the error is in a numeric constant) |
25 | | -
|
26 | | - Approach: |
27 | | -
|
28 | | - First, check if the source consists entirely of blank lines and |
29 | | - comments; if so, replace it with 'pass', because the built-in |
30 | | - parser doesn't always do the right thing for these. |
31 | | -
|
32 | | - Compile three times: as is, with \n, and with \n\n appended. If |
33 | | - it compiles as is, it's complete. If it compiles with one \n |
34 | | - appended, we expect more. If it doesn't compile either way, we |
35 | | - compare the error we get when compiling with \n or \n\n appended. |
36 | | - If the errors are the same, the code is broken. But if the errors |
37 | | - are different, we expect more. Not intuitive; not even guaranteed |
38 | | - to hold in future releases; but this matches the compiler's |
39 | | - behavior from Python 1.4 through 1.5.2, at least. |
40 | | -
|
41 | | - Caveat: |
42 | | -
|
43 | | - It is possible (but not likely) that the parser stops parsing |
44 | | - with a successful outcome before reaching the end of the source; |
45 | | - in this case, trailing symbols may be ignored instead of causing an |
46 | | - error. For example, a backslash followed by two newlines may be |
47 | | - followed by arbitrary garbage. This will be fixed once the API |
48 | | - for the parser is better. |
49 | | -
|
50 | | - """ |
51 | | - |
52 | | - # Check for source consisting of only blank lines and comments |
53 | | - for line in string.split(source, "\n"): |
54 | | - line = string.strip(line) |
55 | | - if line and line[0] != '#': |
56 | | - break # Leave it alone |
57 | | - else: |
58 | | - source = "pass" # Replace it with a 'pass' statement |
59 | | - |
60 | | - err = err1 = err2 = None |
61 | | - code = code1 = code2 = None |
62 | | - |
63 | | - try: |
64 | | - code = compile(source, filename, symbol) |
65 | | - except SyntaxError, err: |
66 | | - pass |
67 | | - |
68 | | - try: |
69 | | - code1 = compile(source + "\n", filename, symbol) |
70 | | - except SyntaxError, err1: |
71 | | - pass |
72 | | - |
73 | | - try: |
74 | | - code2 = compile(source + "\n\n", filename, symbol) |
75 | | - except SyntaxError, err2: |
76 | | - pass |
77 | | - |
78 | | - if code: |
79 | | - return code |
80 | | - try: |
81 | | - e1 = err1.__dict__ |
82 | | - except AttributeError: |
83 | | - e1 = err1 |
84 | | - try: |
85 | | - e2 = err2.__dict__ |
86 | | - except AttributeError: |
87 | | - e2 = err2 |
88 | | - if not code1 and e1 == e2: |
89 | | - raise SyntaxError, err1 |
| 10 | +from codeop import compile_command |
90 | 11 |
|
91 | 12 |
|
92 | 13 | class InteractiveInterpreter: |
|
0 commit comments