diff options
Diffstat (limited to 'Mac/Tools/IDE/PyInteractive.py')
-rw-r--r-- | Mac/Tools/IDE/PyInteractive.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/Mac/Tools/IDE/PyInteractive.py b/Mac/Tools/IDE/PyInteractive.py new file mode 100644 index 0000000..dc75e4b --- /dev/null +++ b/Mac/Tools/IDE/PyInteractive.py @@ -0,0 +1,115 @@ +import string +import sys +import traceback + + +try: + sys.ps1 +except AttributeError: + sys.ps1 = ">>> " +try: + sys.ps2 +except AttributeError: + sys.ps2 = "... " + + +def print_exc(limit=None, file=None): + if not file: + file = sys.stderr + # we're going to skip the outermost traceback object, we don't + # want people to see the line which excecuted their code. + tb = sys.exc_traceback + if tb: + tb = tb.tb_next + try: + sys.last_type = sys.exc_type + sys.last_value = sys.exc_value + sys.last_traceback = tb + traceback.print_exception(sys.last_type, sys.last_value, + sys.last_traceback, limit, file) + except: + print '--- hola! ---' + traceback.print_exception(sys.exc_type, sys.exc_value, + sys.exc_traceback, limit, file) + + +class PyInteractive: + + def __init__(self): + self._pybuf = "" + + def executeline(self, stuff, out = None, env = None): + if env is None: + import __main__ + env = __main__.__dict__ + if out: + saveerr, saveout = sys.stderr, sys.stdout + sys.stderr = sys.stdout = out + try: + if self._pybuf: + self._pybuf = self._pybuf + '\n' + stuff + else: + self._pybuf = stuff + + # 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 + + # quickly get out of here when the line is 'empty' or is a comment + stripped = string.strip(self._pybuf) + if not stripped or stripped[0] == '#': + self._pybuf = '' + sys.stdout.write(sys.ps1) + sys.stdout.flush() + return + + try: + code = compile(self._pybuf, "<input>", "single") + except SyntaxError, err: + pass + except: + # OverflowError. More? + print_exc() + self._pybuf = "" + sys.stdout.write(sys.ps1) + sys.stdout.flush() + return + + try: + code1 = compile(self._pybuf + "\n", "<input>", "single") + except SyntaxError, err1: + pass + + try: + code2 = compile(self._pybuf + "\n\n", "<input>", "single") + except SyntaxError, err2: + pass + + if code: + try: + exec code in env + except: + print_exc() + self._pybuf = "" + elif code1: + pass + elif err1 == err2 or (not stuff and self._pybuf): + print_exc() + self._pybuf = "" + if self._pybuf: + sys.stdout.write(sys.ps2) + sys.stdout.flush() + else: + sys.stdout.write(sys.ps1) + sys.stdout.flush() + finally: + if out: + sys.stderr, sys.stdout = saveerr, saveout |