diff options
-rw-r--r-- | Lib/code.py | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/Lib/code.py b/Lib/code.py new file mode 100644 index 0000000..49fe541 --- /dev/null +++ b/Lib/code.py @@ -0,0 +1,52 @@ +"""Utilities dealing with code objects.""" + +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 / exception raised: + + - Return a code object if the command is complete and valid + - Return None if the command is incomplete + - Raise SyntaxError if the command is a syntax error + + Approach: + + 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 in Python 1.4 and 1.5. + + """ + + err = err1 = err2 = None + code = code1 = code2 = None + + try: + code = compile(source, filename, symbol) + except SyntaxError, err: + pass + + try: + code1 = compile(source + "\n", filename, symbol) + except SyntaxError, err1: + pass + + try: + code2 = compile(source + "\n\n", filename, symbol) + except SyntaxError, err2: + pass + + if code: + return code + if not code1 and err1 == err2: + raise SyntaxError, err1 |