summaryrefslogtreecommitdiff
path: root/paste/printdebug.py
diff options
context:
space:
mode:
Diffstat (limited to 'paste/printdebug.py')
-rw-r--r--paste/printdebug.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/paste/printdebug.py b/paste/printdebug.py
new file mode 100644
index 0000000..280356f
--- /dev/null
+++ b/paste/printdebug.py
@@ -0,0 +1,87 @@
+import sys
+from cStringIO import StringIO
+import re
+import cgi
+from paste.util import threadedprint
+from paste import wsgilib
+
+_threadedprint_installed = False
+
+__all__ = ['PrintDebugMiddleware']
+
+class TeeFile(object):
+
+ def __init__(self, *files):
+ self.files = files
+
+ def write(self, v):
+ for file in self.files:
+ file.write(v)
+
+class PrintDebugMiddleware(object):
+
+ """
+ This middleware captures all the printed statements, and inlines
+ them in HTML pages, so that you can see all the (debug-intended)
+ print statements in the page itself. Install like::
+
+ important_middleware.append(
+ 'paste.printdebug.PrintDebugMiddleware')
+
+ In your configuration file.
+ """
+
+ log_template = (
+ '<pre style="width: 40%%; border: 2px solid #000; '
+ 'background-color: #ffd; color: #000; float: right;">'
+ '<b style="border-bottom: 1px solid #000">Log messages</b><br>'
+ '%s</pre>')
+
+ def __init__(self, subapp):
+ self.subapp = subapp
+
+ def __call__(self, environ, start_response):
+ global _threadedprint_installed
+ if not _threadedprint_installed:
+ # @@: Not strictly threadsafe
+ _threadedprint_installed = True
+ threadedprint.install(leave_stdout=True)
+ logged = StringIO()
+ if environ['paste.config'].get('printdebug_print_error'):
+ replacement_stdout = TeeFile(environ['wsgi.errors'], logged)
+ else:
+ replacement_stdout = logged
+ output = StringIO()
+ try:
+ threadedprint.register(replacement_stdout)
+ status, headers, body = wsgilib.capture_output(
+ environ, start_response, self.subapp)
+ if status is None:
+ # Some error occurred
+ status = '500 Server Error'
+ headers = [('Content-type', 'text/html')]
+ start_response(status, headers)
+ if not body:
+ body = 'An error occurred'
+ content_type = wsgilib.header_value(headers, 'content-type')
+ if not content_type or not content_type.startswith('text/html'):
+ if replacement_stdout == logged:
+ # Then the prints will be lost, unless...
+ environ['wsgi.errors'].write(logged.getvalue())
+ return [body]
+ body = self.add_log(body, logged.getvalue())
+ return [body]
+ finally:
+ threadedprint.deregister()
+
+ _body_re = re.compile(r'<body[^>]*>', re.I)
+
+ def add_log(self, html, log):
+ if not log:
+ return html
+ log = self.log_template % cgi.escape(log)
+ match = self._body_re.search(html)
+ if not match:
+ return log + html
+ else:
+ return html[:match.end()] + log + html[match.end():]