diff options
| author | ianb <devnull@localhost> | 2005-12-18 21:33:14 +0000 |
|---|---|---|
| committer | ianb <devnull@localhost> | 2005-12-18 21:33:14 +0000 |
| commit | d5820c427e86c482ec47c3e607e6f7f535e88396 (patch) | |
| tree | b3278cb0f71af9f04b9511f7f49fbb9966e213e3 /paste/debug | |
| parent | 4f3e0083b010a2e90b95ef1563bb06db45ad026b (diff) | |
| download | paste-d5820c427e86c482ec47c3e607e6f7f535e88396.tar.gz | |
Moved paste.printdebug to paste.debug.prints
Diffstat (limited to 'paste/debug')
| -rw-r--r-- | paste/debug/prints.py | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/paste/debug/prints.py b/paste/debug/prints.py new file mode 100644 index 0000000..973322e --- /dev/null +++ b/paste/debug/prints.py @@ -0,0 +1,103 @@ +# (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 cStringIO import StringIO +import re +import cgi +from paste.util import threadedprint +from paste import wsgilib +from paste.deploy.converters import asbool + +_threadedprint_installed = False + +__all__ = ['PrintDebugMiddleware'] + +class TeeFile(object): + + def __init__(self, *files): + self.files = files + + def write(self, v): + if isinstance(v, unicode): + # WSGI is picky in this case + v = str(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. + """ + + log_template = ( + '<pre style="width: 40%%; border: 2px solid #000; white-space: normal; ' + 'background-color: #ffd; color: #000; float: right;">' + '<b style="border-bottom: 1px solid #000">Log messages</b><br>' + '%s</pre>') + + def __init__(self, app, global_conf=None, force_content_type=False, + print_wsgi_errors=True): + self.app = app + self.force_content_type = force_content_type + self.print_wsgi_errors = asbool(print_wsgi_errors) + + def __call__(self, environ, start_response): + global _threadedprint_installed + if environ.get('paste.testing'): + # In a testing environment this interception isn't + # useful: + return self.app(environ, start_response) + if not _threadedprint_installed: + # @@: Not strictly threadsafe + _threadedprint_installed = True + threadedprint.install(leave_stdout=True) + logged = StringIO() + if self.print_wsgi_errors: + replacement_stdout = TeeFile(environ['wsgi.errors'], logged) + else: + replacement_stdout = logged + output = StringIO() + try: + threadedprint.register(replacement_stdout) + status, headers, body = wsgilib.intercept_output( + environ, self.app) + 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 self.force_content_type and + (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()) + start_response(status, headers) + return [body] + wsgilib.remove_header(headers, 'content-length') + body = self.add_log(body, logged.getvalue()) + start_response(status, headers) + return [body] + finally: + threadedprint.deregister() + + _body_re = re.compile(r'<body[^>]*>', re.I) + + def add_log(self, html, log): + if not log: + return html + text = cgi.escape(log) + text = text.replace('\n', '<br>\n') + text = text.replace(' ', ' ') + log = self.log_template % text + match = self._body_re.search(html) + if not match: + return log + html + else: + return html[:match.end()] + log + html[match.end():] |
