root/galaxy-central/eggs/Paste-1.6-py2.6.egg/paste/debug/prints.py @ 3

リビジョン 3, 5.1 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
2# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
3"""
4Middleware that displays everything that is printed inline in
5application pages.
6
7Anything printed during the request will get captured and included on
8the page.  It will usually be included as a floating element in the
9top right hand corner of the page.  If you want to override this
10you can include a tag in your template where it will be placed::
11
12  <pre id="paste-debug-prints"></pre>
13
14You might want to include ``style="white-space: normal"``, as all the
15whitespace will be quoted, and this allows the text to wrap if
16necessary.
17
18"""
19
20from cStringIO import StringIO
21import re
22import cgi
23from paste.util import threadedprint
24from paste import wsgilib
25from paste import response
26
27_threadedprint_installed = False
28
29__all__ = ['PrintDebugMiddleware']
30
31class TeeFile(object):
32
33    def __init__(self, files):
34        self.files = files
35
36    def write(self, v):
37        if isinstance(v, unicode):
38            # WSGI is picky in this case
39            v = str(v)
40        for file in self.files:
41            file.write(v)
42
43class PrintDebugMiddleware(object):
44
45    """
46    This middleware captures all the printed statements, and inlines
47    them in HTML pages, so that you can see all the (debug-intended)
48    print statements in the page itself.
49
50    There are two keys added to the environment to control this:
51    ``environ['paste.printdebug_listeners']`` is a list of functions
52    that will be called everytime something is printed.
53
54    ``environ['paste.remove_printdebug']`` is a function that, if
55    called, will disable printing of output for that request.
56    """
57
58    log_template = (
59        '<pre style="width: 40%%; border: 2px solid #000; white-space: normal; '
60        'background-color: #ffd; color: #000; float: right;">'
61        '<b style="border-bottom: 1px solid #000">Log messages</b><br>'
62        '%s</pre>')
63
64    def __init__(self, app, global_conf=None, force_content_type=False,
65                 print_wsgi_errors=True):
66        # @@: global_conf should be handled separately and only for
67        # the entry point
68        self.app = app
69        self.force_content_type = force_content_type
70        if isinstance(print_wsgi_errors, basestring):
71            from paste.deploy.converters import asbool
72            print_wsgi_errors = asbool(print_wsgi_errors)
73        self.print_wsgi_errors = print_wsgi_errors
74
75    def __call__(self, environ, start_response):
76        global _threadedprint_installed
77        if environ.get('paste.testing'):
78            # In a testing environment this interception isn't
79            # useful:
80            return self.app(environ, start_response)
81        if not _threadedprint_installed:
82            # @@: Not strictly threadsafe
83            _threadedprint_installed = True
84            threadedprint.install(leave_stdout=True)
85        removed = []
86        def remove_printdebug():
87            removed.append(None)
88        environ['paste.remove_printdebug'] = remove_printdebug
89        logged = StringIO()
90        listeners = [logged]
91        environ['paste.printdebug_listeners'] = listeners
92        if self.print_wsgi_errors:
93            listeners.append(environ['wsgi.errors'])
94        replacement_stdout = TeeFile(listeners)
95        threadedprint.register(replacement_stdout)
96        try:
97            status, headers, body = wsgilib.intercept_output(
98                environ, self.app)
99            if status is None:
100                # Some error occurred
101                status = '500 Server Error'
102                headers = [('Content-type', 'text/html')]
103                start_response(status, headers)
104                if not body:
105                    body = 'An error occurred'
106            content_type = response.header_value(headers, 'content-type')
107            if (removed or
108                (not self.force_content_type and
109                 (not content_type
110                  or not content_type.startswith('text/html')))):
111                if replacement_stdout == logged:
112                    # Then the prints will be lost, unless...
113                    environ['wsgi.errors'].write(logged.getvalue())
114                start_response(status, headers)
115                return [body]
116            response.remove_header(headers, 'content-length')
117            body = self.add_log(body, logged.getvalue())
118            start_response(status, headers)
119            return [body]
120        finally:
121            threadedprint.deregister()
122
123    _body_re = re.compile(r'<body[^>]*>', re.I)
124    _explicit_re = re.compile(r'<pre\s*[^>]*id="paste-debug-prints".*?>',
125                              re.I+re.S)
126   
127    def add_log(self, html, log):
128        if not log:
129            return html
130        text = cgi.escape(log)
131        text = text.replace('\n', '<br>')
132        text = text.replace('  ', '&nbsp; ')
133        match = self._explicit_re.search(html)
134        if not match:
135            text = self.log_template % text
136            match = self._body_re.search(html)
137        if not match:
138            return text + html
139        else:
140            return html[:match.end()] + text + html[match.end():]
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。