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): import codeop self._pybuf = "" self._compile = codeop.Compile() 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 = self._compile(self._pybuf, "", "single") except SyntaxError, err: pass except: # OverflowError. More? print_exc() self._pybuf = "" sys.stdout.write(sys.ps1) sys.stdout.flush() return try: code1 = self._compile(self._pybuf + "\n", "", "single") except SyntaxError, err1: pass try: code2 = self._compile(self._pybuf + "\n\n", "", "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