summaryrefslogtreecommitdiff
path: root/paste/evalexception/evalcontext.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/evalexception/evalcontext.py')
-rw-r--r--paste/evalexception/evalcontext.py69
1 files changed, 69 insertions, 0 deletions
diff --git a/paste/evalexception/evalcontext.py b/paste/evalexception/evalcontext.py
new file mode 100644
index 0000000..42f2efa
--- /dev/null
+++ b/paste/evalexception/evalcontext.py
@@ -0,0 +1,69 @@
+# (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