# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php from six.moves import cStringIO as StringIO import traceback import threading import pdb import six import sys exec_lock = threading.Lock() class EvalContext(object): """ Class that represents a interactive interface. It has its own namespace. Use eval_context.exec_expr(expr) to run commands; the output of those commands is returned, as are print statements. This is essentially what doctest does, and is taken directly from doctest. """ def __init__(self, namespace, globs): self.namespace = namespace self.globs = globs def exec_expr(self, s): out = StringIO() exec_lock.acquire() save_stdout = sys.stdout try: debugger = _OutputRedirectingPdb(save_stdout) debugger.reset() pdb.set_trace = debugger.set_trace sys.stdout = out try: code = compile(s, '<web>', "single", 0, 1) six.exec_(code, self.globs, self.namespace) debugger.set_continue() except KeyboardInterrupt: raise except: traceback.print_exc(file=out) debugger.set_continue() finally: sys.stdout = save_stdout exec_lock.release() return out.getvalue() # From doctest class _OutputRedirectingPdb(pdb.Pdb): """ A specialized version of the python debugger that redirects stdout to a given stream when interacting with the user. Stdout is *not* redirected when traced code is executed. """ def __init__(self, out): self.__out = out pdb.Pdb.__init__(self) def trace_dispatch(self, *args): # Redirect stdout to the given stream. save_stdout = sys.stdout sys.stdout = self.__out # Call Pdb's trace dispatch method. try: return pdb.Pdb.trace_dispatch(self, *args) finally: sys.stdout = save_stdout