comparison MoinMoin/support/werkzeug/testapp.py @ 5801:8de563c487be

upgrade werkzeug to 0.8.1, document current bundled version and current minimum requirement (0.6, for py 2.7 compatibility)
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Thu, 01 Dec 2011 01:34:45 +0100
parents 246ba4eecab2
children 9f12f41504fc
comparison
equal deleted inserted replaced
5800:4ab3c578e44b 5801:8de563c487be
4 ~~~~~~~~~~~~~~~~ 4 ~~~~~~~~~~~~~~~~
5 5
6 Provide a small test application that can be used to test a WSGI server 6 Provide a small test application that can be used to test a WSGI server
7 and check it for WSGI compliance. 7 and check it for WSGI compliance.
8 8
9 :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details. 9 :copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
10 :license: BSD, see LICENSE for more details. 10 :license: BSD, see LICENSE for more details.
11 """ 11 """
12 from werkzeug.templates import Template 12 import os
13 import sys
14 import werkzeug
15 from textwrap import wrap
13 from werkzeug.wrappers import BaseRequest as Request, BaseResponse as Response 16 from werkzeug.wrappers import BaseRequest as Request, BaseResponse as Response
17 from werkzeug.utils import escape
14 18
15 19
16 logo = Response('''R0lGODlhoACgAOMIAAEDACwpAEpCAGdgAJaKAM28AOnVAP3rAP///////// 20 logo = Response('''R0lGODlhoACgAOMIAAEDACwpAEpCAGdgAJaKAM28AOnVAP3rAP/////////
17 //////////////////////yH5BAEKAAgALAAAAACgAKAAAAT+EMlJq704680R+F0ojmRpnuj0rWnrv 21 //////////////////////yH5BAEKAAgALAAAAACgAKAAAAT+EMlJq704680R+F0ojmRpnuj0rWnrv
18 nB8rbRs33gu0bzu/0AObxgsGn3D5HHJbCUFyqZ0ukkSDlAidctNFg7gbI9LZlrBaHGtzAae0eloe25 22 nB8rbRs33gu0bzu/0AObxgsGn3D5HHJbCUFyqZ0ukkSDlAidctNFg7gbI9LZlrBaHGtzAae0eloe25
47 aDs2Sg7MBS6xnQeooc2R2tC9YrKpEi9pLXfYXp20tDCpSP8rKlrD4axprb9u1Df5hSbz9QU0cRpfgn 51 aDs2Sg7MBS6xnQeooc2R2tC9YrKpEi9pLXfYXp20tDCpSP8rKlrD4axprb9u1Df5hSbz9QU0cRpfgn
48 kiIzwKucd0wsEHlLpe5yHXuc6FrNelOl7pY2+11kTWx7VpRu97dXA3DO1vbkhcb4zyvERYajQgAADs 52 kiIzwKucd0wsEHlLpe5yHXuc6FrNelOl7pY2+11kTWx7VpRu97dXA3DO1vbkhcb4zyvERYajQgAADs
49 ='''.decode('base64'), mimetype='image/png') 53 ='''.decode('base64'), mimetype='image/png')
50 54
51 55
52 TEMPLATE = Template(ur'''\ 56 TEMPLATE = u'''\
53 <%py 57 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
54 import sys, os 58 "http://www.w3.org/TR/html4/loose.dtd">
55 from textwrap import wrap 59 <title>WSGI Information</title>
60 <style type="text/css">
61 @import url(http://fonts.googleapis.com/css?family=Ubuntu);
62
63 body { font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
64 'Verdana', sans-serif; background-color: white; color: #000;
65 font-size: 15px; text-align: center; }
66 #logo { float: right; padding: 0 0 10px 10px; }
67 div.box { text-align: left; width: 45em; margin: auto; padding: 50px 0;
68 background-color: white; }
69 h1, h2 { font-family: 'Ubuntu', 'Lucida Grande', 'Lucida Sans Unicode',
70 'Geneva', 'Verdana', sans-serif; font-weight: normal; }
71 h1 { margin: 0 0 30px 0; }
72 h2 { font-size: 1.4em; margin: 1em 0 0.5em 0; }
73 table { width: 100%%; border-collapse: collapse; border: 1px solid #AFC5C9 }
74 table th { background-color: #AFC1C4; color: white; font-size: 0.72em;
75 font-weight: normal; width: 18em; vertical-align: top;
76 padding: 0.5em 0 0.1em 0.5em; }
77 table td { border: 1px solid #AFC5C9; padding: 0.1em 0 0.1em 0.5em; }
78 code { font-family: 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono',
79 monospace; font-size: 0.7em; }
80 ul li { line-height: 1.5em; }
81 ul.path { font-size: 0.7em; margin: 0 -30px; padding: 8px 30px;
82 list-style: none; background: #E8EFF0; }
83 ul.path li { line-height: 1.6em; }
84 li.virtual { color: #999; text-decoration: underline; }
85 li.exp { background: white; }
86 </style>
87 <div class="box">
88 <img src="?resource=logo" id="logo" alt="[The Werkzeug Logo]" />
89 <h1>WSGI Information</h1>
90 <p>
91 This page displays all available information about the WSGI server and
92 the underlying Python interpreter.
93 <h2 id="python-interpreter">Python Interpreter</h2>
94 <table>
95 <tr>
96 <th>Python Version
97 <td>%(python_version)s
98 <tr>
99 <th>Platform
100 <td>%(platform)s [%(os)s]
101 <tr>
102 <th>API Version
103 <td>%(api_version)s
104 <tr>
105 <th>Byteorder
106 <td>%(byteorder)s
107 <tr>
108 <th>Werkzeug Version
109 <td>%(werkzeug_version)s
110 </table>
111 <h2 id="wsgi-environment">WSGI Environment</h2>
112 <table>%(wsgi_env)s</table>
113 <h2 id="installed-eggs">Installed Eggs</h2>
114 <p>
115 The following python packages were installed on the system as
116 Python eggs:
117 <ul>%(python_eggs)s</ul>
118 <h2 id="sys-path">System Path</h2>
119 <p>
120 The following paths are the current contents of the load path. The
121 following entries are looked up for Python packages. Note that not
122 all items in this path are folders. Gray and underlined items are
123 entries pointing to invalid resources or used by custom import hooks
124 such as the zip importer.
125 <p>
126 Items with a bright background were expanded for display from a relative
127 path. If you encounter such paths in the output you might want to check
128 your setup as relative paths are usually problematic in multithreaded
129 environments.
130 <ul class="path">%(sys_path)s</ul>
131 </div>
132 '''
133
134
135 def iter_sys_path():
136 if os.name == 'posix':
137 def strip(x):
138 prefix = os.path.expanduser('~')
139 if x.startswith(prefix):
140 x = '~' + x[len(prefix):]
141 return x
142 else:
143 strip = lambda x: x
144
145 cwd = os.path.abspath(os.getcwd())
146 for item in sys.path:
147 path = os.path.join(cwd, item or os.path.curdir)
148 yield strip(os.path.normpath(path)), \
149 not os.path.isdir(path), path != item
150
151
152 def render_testapp(req):
56 try: 153 try:
57 import pkg_resources 154 import pkg_resources
58 except ImportError: 155 except ImportError:
59 eggs = None 156 eggs = ()
60 else: 157 else:
61 eggs = list(pkg_resources.working_set) 158 eggs = list(pkg_resources.working_set)
62 eggs.sort(lambda a, b: cmp(a.project_name.lower(), 159 eggs.sort(lambda a, b: cmp(a.project_name.lower(),
63 b.project_name.lower())) 160 b.project_name.lower()))
161 python_eggs = []
162 for egg in eggs:
163 try:
164 version = egg.version
165 except (ValueError, AttributeError):
166 version = 'unknown'
167 python_eggs.append('<li>%s <small>[%s]</small>' % (
168 escape(egg.project_name),
169 escape(version)
170 ))
171
172 wsgi_env = []
64 sorted_environ = req.environ.items() 173 sorted_environ = req.environ.items()
65 sorted_environ.sort(lambda a, b: cmp(str(a[0]).lower(), str(b[0]).lower())) 174 sorted_environ.sort(key=lambda x: repr(x[0]).lower())
66 %> 175 for key, value in sorted_environ:
67 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 176 wsgi_env.append('<tr><th>%s<td><code>%s</code>' % (
68 "http://www.w3.org/TR/html4/loose.dtd"> 177 escape(str(key)),
69 <title>WSGI Information</title> 178 ' '.join(wrap(escape(repr(value))))
70 <style type="text/css"> 179 ))
71 body { font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 180
72 'Verdana', sans-serif; background-color: #AFC1C4; color: #000; 181 sys_path = []
73 text-align: center; margin: 1em; padding: 0; } 182 for item, virtual, expanded in iter_sys_path():
74 #logo { float: right; padding: 10px; } 183 class_ = []
75 div.box { text-align: left; width: 45em; padding: 1em; margin: auto; 184 if virtual:
76 border: 1px solid #aaa; background-color: white; } 185 class_.append('virtual')
77 h1 { color: #11557C; font-size: 2em; margin: 0 0 0.8em 0; } 186 if expanded:
78 h2 { font-size: 1.4em; margin: 1em 0 0.5em 0; } 187 class_.append('exp')
79 table { width: 100%; border-collapse: collapse; border: 1px solid #AFC5C9 } 188 sys_path.append('<li%s>%s' % (
80 table th { background-color: #AFC1C4; color: white; font-size: 0.72em; 189 class_ and ' class="%s"' % ' '.join(class_) or '',
81 font-weight: normal; width: 18em; vertical-align: top; 190 escape(item)
82 padding: 0.5em 0 0.1em 0.5em; } 191 ))
83 table td { border: 1px solid #AFC5C9; padding: 0.1em 0 0.1em 0.5em; } 192
84 code { font-family: 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono', 193 return TEMPLATE % {
85 monospace; font-size: 0.7em; } 194 'python_version': '<br>'.join(escape(sys.version).splitlines()),
86 ul li { line-height: 1.5em; } 195 'platform': escape(sys.platform),
87 </style> 196 'os': escape(os.name),
88 <div class="box"> 197 'api_version': sys.api_version,
89 <img src="?resource=logo" id="logo" alt="[The Werkzeug Logo]" /> 198 'byteorder': sys.byteorder,
90 <h1>WSGI Information</h1> 199 'werkzeug_version': werkzeug.__version__,
91 <p> 200 'python_eggs': '\n'.join(python_eggs),
92 This page displays all available information about the WSGI server and 201 'wsgi_env': '\n'.join(wsgi_env),
93 the underlying Python interpreter that are available. 202 'sys_path': '\n'.join(sys_path)
94 </p> 203 }
95 <h2 id="python-interpreter">Python Interpreter</h2>
96 <table>
97 <tr>
98 <th>Python Version</th>
99 <td>${'<br>'.join(escape(sys.version).splitlines())}</td>
100 </tr>
101 <tr>
102 <th>Platform</th>
103 <td>$escape(sys.platform) [$escape(os.name)]</td>
104 </tr>
105 <tr>
106 <th>API Version</th>
107 <td>$sys.api_version</td>
108 </tr>
109 <tr>
110 <th>Byteorder</th>
111 <td>$sys.byteorder</td>
112 </tr>
113 </table>
114 <h2 id="wsgi-environment">WSGI Environment</h2>
115 <table>
116 <% for key, value in sorted_environ %>
117 <tr>
118 <th>$escape(str(key))</th>
119 <td><code>${' '.join(wrap(escape(repr(value))))}</code></td>
120 </tr>
121 <% endfor %>
122 </table>
123 <% if eggs %>
124 <h2 id="installed-eggs">Installed Eggs</h2>
125 <ul>
126 <% for egg in eggs %>
127 <li>$escape(egg.project_name) <small>[$escape(egg.version)]</small></li>
128 <% endfor %>
129 </ul>
130 <% endif %>
131 </div>''')
132 204
133 205
134 def test_app(environ, start_response): 206 def test_app(environ, start_response):
135 """Simple test application that dumps the environment.""" 207 """Simple test application that dumps the environment. You can use
208 it to check if Werkzeug is working properly:
209
210 .. sourcecode:: pycon
211
212 >>> from werkzeug.serving import run_simple
213 >>> from werkzeug.testapp import test_app
214 >>> run_simple('localhost', 3000, test_app)
215 * Running on http://localhost:3000/
216
217 The application displays important information from the WSGI environment,
218 the Python interpreter and the installed libraries.
219 """
136 req = Request(environ, populate_request=False) 220 req = Request(environ, populate_request=False)
137 if req.args.get('resource') == 'logo': 221 if req.args.get('resource') == 'logo':
138 response = logo 222 response = logo
139 else: 223 else:
140 response = Response(TEMPLATE.render(req=req), mimetype='text/html') 224 response = Response(render_testapp(req), mimetype='text/html')
141 return response(environ, start_response) 225 return response(environ, start_response)
142 226
143 227
144 if __name__ == '__main__': 228 if __name__ == '__main__':
145 from werkzeug.serving import run_simple 229 from werkzeug.serving import run_simple