diff 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
line wrap: on
line diff
--- a/MoinMoin/support/werkzeug/testapp.py	Sat Mar 12 23:48:11 2011 +0100
+++ b/MoinMoin/support/werkzeug/testapp.py	Thu Dec 01 01:34:45 2011 +0100
@@ -6,11 +6,15 @@
     Provide a small test application that can be used to test a WSGI server
     and check it for WSGI compliance.
 
-    :copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
+    :copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
     :license: BSD, see LICENSE for more details.
 """
-from werkzeug.templates import Template
+import os
+import sys
+import werkzeug
+from textwrap import wrap
 from werkzeug.wrappers import BaseRequest as Request, BaseResponse as Response
+from werkzeug.utils import escape
 
 
 logo = Response('''R0lGODlhoACgAOMIAAEDACwpAEpCAGdgAJaKAM28AOnVAP3rAP/////////
@@ -49,95 +53,175 @@
 ='''.decode('base64'), mimetype='image/png')
 
 
-TEMPLATE = Template(ur'''\
-<%py
-    import sys, os
-    from textwrap import wrap
-    try:
-        import pkg_resources
-    except ImportError:
-        eggs = None
-    else:
-        eggs = list(pkg_resources.working_set)
-        eggs.sort(lambda a, b: cmp(a.project_name.lower(),
-                                   b.project_name.lower()))
-    sorted_environ = req.environ.items()
-    sorted_environ.sort(lambda a, b: cmp(str(a[0]).lower(), str(b[0]).lower()))
-%>
+TEMPLATE = u'''\
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">
 <title>WSGI Information</title>
 <style type="text/css">
-  body      { font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
-              'Verdana', sans-serif; background-color: #AFC1C4; color: #000;
-              text-align: center; margin: 1em; padding: 0; }
-  #logo     { float: right; padding: 10px; }
-  div.box   { text-align: left; width: 45em; padding: 1em; margin: auto;
-              border: 1px solid #aaa; background-color: white; }
-  h1        { color: #11557C; font-size: 2em; margin: 0 0 0.8em 0; }
-  h2        { font-size: 1.4em; margin: 1em 0 0.5em 0; }
-  table     { width: 100%; border-collapse: collapse; border: 1px solid #AFC5C9 }
-  table th  { background-color: #AFC1C4; color: white; font-size: 0.72em;
-              font-weight: normal; width: 18em; vertical-align: top;
-              padding: 0.5em 0 0.1em 0.5em; }
-  table td  { border: 1px solid #AFC5C9; padding: 0.1em 0 0.1em 0.5em; }
-  code      { font-family: 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono',
-              monospace; font-size: 0.7em; }
-  ul li     { line-height: 1.5em; }
+  @import url(http://fonts.googleapis.com/css?family=Ubuntu);
+
+  body       { font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+               'Verdana', sans-serif; background-color: white; color: #000;
+               font-size: 15px; text-align: center; }
+  #logo      { float: right; padding: 0 0 10px 10px; }
+  div.box    { text-align: left; width: 45em; margin: auto; padding: 50px 0;
+               background-color: white; }
+  h1, h2     { font-family: 'Ubuntu', 'Lucida Grande', 'Lucida Sans Unicode',
+               'Geneva', 'Verdana', sans-serif; font-weight: normal; }
+  h1         { margin: 0 0 30px 0; }
+  h2         { font-size: 1.4em; margin: 1em 0 0.5em 0; }
+  table      { width: 100%%; border-collapse: collapse; border: 1px solid #AFC5C9 }
+  table th   { background-color: #AFC1C4; color: white; font-size: 0.72em;
+               font-weight: normal; width: 18em; vertical-align: top;
+               padding: 0.5em 0 0.1em 0.5em; }
+  table td   { border: 1px solid #AFC5C9; padding: 0.1em 0 0.1em 0.5em; }
+  code       { font-family: 'Consolas', 'Monaco', 'Bitstream Vera Sans Mono',
+               monospace; font-size: 0.7em; }
+  ul li      { line-height: 1.5em; }
+  ul.path    { font-size: 0.7em; margin: 0 -30px; padding: 8px 30px;
+               list-style: none; background: #E8EFF0; }
+  ul.path li { line-height: 1.6em; }
+  li.virtual { color: #999; text-decoration: underline; }
+  li.exp     { background: white; }
 </style>
 <div class="box">
   <img src="?resource=logo" id="logo" alt="[The Werkzeug Logo]" />
   <h1>WSGI Information</h1>
   <p>
     This page displays all available information about the WSGI server and
-    the underlying Python interpreter that are available.
-  </p>
+    the underlying Python interpreter.
   <h2 id="python-interpreter">Python Interpreter</h2>
   <table>
     <tr>
-      <th>Python Version</th>
-      <td>${'<br>'.join(escape(sys.version).splitlines())}</td>
-    </tr>
+      <th>Python Version
+      <td>%(python_version)s
     <tr>
-      <th>Platform</th>
-      <td>$escape(sys.platform) [$escape(os.name)]</td>
-    </tr>
+      <th>Platform
+      <td>%(platform)s [%(os)s]
     <tr>
-      <th>API Version</th>
-      <td>$sys.api_version</td>
-    </tr>
+      <th>API Version
+      <td>%(api_version)s
     <tr>
-      <th>Byteorder</th>
-      <td>$sys.byteorder</td>
-    </tr>
+      <th>Byteorder
+      <td>%(byteorder)s
+    <tr>
+      <th>Werkzeug Version
+      <td>%(werkzeug_version)s
   </table>
   <h2 id="wsgi-environment">WSGI Environment</h2>
-  <table>
-  <% for key, value in sorted_environ %>
-    <tr>
-      <th>$escape(str(key))</th>
-      <td><code>${' '.join(wrap(escape(repr(value))))}</code></td>
-    </tr>
-  <% endfor %>
-  </table>
-  <% if eggs %>
+  <table>%(wsgi_env)s</table>
   <h2 id="installed-eggs">Installed Eggs</h2>
-  <ul>
-  <% for egg in eggs %>
-    <li>$escape(egg.project_name) <small>[$escape(egg.version)]</small></li>
-  <% endfor %>
-  </ul>
-  <% endif %>
-</div>''')
+  <p>
+    The following python packages were installed on the system as
+    Python eggs:
+  <ul>%(python_eggs)s</ul>
+  <h2 id="sys-path">System Path</h2>
+  <p>
+    The following paths are the current contents of the load path.  The
+    following entries are looked up for Python packages.  Note that not
+    all items in this path are folders.  Gray and underlined items are
+    entries pointing to invalid resources or used by custom import hooks
+    such as the zip importer.
+  <p>
+    Items with a bright background were expanded for display from a relative
+    path.  If you encounter such paths in the output you might want to check
+    your setup as relative paths are usually problematic in multithreaded
+    environments.
+  <ul class="path">%(sys_path)s</ul>
+</div>
+'''
+
+
+def iter_sys_path():
+    if os.name == 'posix':
+        def strip(x):
+            prefix = os.path.expanduser('~')
+            if x.startswith(prefix):
+                x = '~' + x[len(prefix):]
+            return x
+    else:
+        strip = lambda x: x
+
+    cwd = os.path.abspath(os.getcwd())
+    for item in sys.path:
+        path = os.path.join(cwd, item or os.path.curdir)
+        yield strip(os.path.normpath(path)), \
+              not os.path.isdir(path), path != item
+
+
+def render_testapp(req):
+    try:
+        import pkg_resources
+    except ImportError:
+        eggs = ()
+    else:
+        eggs = list(pkg_resources.working_set)
+        eggs.sort(lambda a, b: cmp(a.project_name.lower(),
+                                   b.project_name.lower()))
+    python_eggs = []
+    for egg in eggs:
+        try:
+            version = egg.version
+        except (ValueError, AttributeError):
+            version = 'unknown'
+        python_eggs.append('<li>%s <small>[%s]</small>' % (
+            escape(egg.project_name),
+            escape(version)
+        ))
+
+    wsgi_env = []
+    sorted_environ = req.environ.items()
+    sorted_environ.sort(key=lambda x: repr(x[0]).lower())
+    for key, value in sorted_environ:
+        wsgi_env.append('<tr><th>%s<td><code>%s</code>' % (
+            escape(str(key)),
+            ' '.join(wrap(escape(repr(value))))
+        ))
+
+    sys_path = []
+    for item, virtual, expanded in iter_sys_path():
+        class_ = []
+        if virtual:
+            class_.append('virtual')
+        if expanded:
+            class_.append('exp')
+        sys_path.append('<li%s>%s' % (
+            class_ and ' class="%s"' % ' '.join(class_) or '',
+            escape(item)
+        ))
+
+    return TEMPLATE % {
+        'python_version':   '<br>'.join(escape(sys.version).splitlines()),
+        'platform':         escape(sys.platform),
+        'os':               escape(os.name),
+        'api_version':      sys.api_version,
+        'byteorder':        sys.byteorder,
+        'werkzeug_version': werkzeug.__version__,
+        'python_eggs':      '\n'.join(python_eggs),
+        'wsgi_env':         '\n'.join(wsgi_env),
+        'sys_path':         '\n'.join(sys_path)
+    }
 
 
 def test_app(environ, start_response):
-    """Simple test application that dumps the environment."""
+    """Simple test application that dumps the environment.  You can use
+    it to check if Werkzeug is working properly:
+
+    .. sourcecode:: pycon
+
+        >>> from werkzeug.serving import run_simple
+        >>> from werkzeug.testapp import test_app
+        >>> run_simple('localhost', 3000, test_app)
+         * Running on http://localhost:3000/
+
+    The application displays important information from the WSGI environment,
+    the Python interpreter and the installed libraries.
+    """
     req = Request(environ, populate_request=False)
     if req.args.get('resource') == 'logo':
         response = logo
     else:
-        response = Response(TEMPLATE.render(req=req), mimetype='text/html')
+        response = Response(render_testapp(req), mimetype='text/html')
     return response(environ, start_response)