OSDN Git Service

first commit master
authornagaetty <nagaetty@gmail.com>
Mon, 12 Nov 2012 00:54:09 +0000 (09:54 +0900)
committernagaetty <nagaetty@gmail.com>
Mon, 12 Nov 2012 00:54:09 +0000 (09:54 +0900)
95 files changed:
html/.buildinfo [new file with mode: 0644]
html/.doctrees/api.doctree [new file with mode: 0644]
html/.doctrees/async.doctree [new file with mode: 0644]
html/.doctrees/changelog.doctree [new file with mode: 0644]
html/.doctrees/contact.doctree [new file with mode: 0644]
html/.doctrees/deployment.doctree [new file with mode: 0644]
html/.doctrees/development.doctree [new file with mode: 0644]
html/.doctrees/environment.pickle [new file with mode: 0644]
html/.doctrees/faq.doctree [new file with mode: 0644]
html/.doctrees/index.doctree [new file with mode: 0644]
html/.doctrees/plugindev.doctree [new file with mode: 0644]
html/.doctrees/plugins/index.doctree [new file with mode: 0644]
html/.doctrees/plugins/sqlite.doctree [new file with mode: 0644]
html/.doctrees/plugins/werkzeug.doctree [new file with mode: 0644]
html/.doctrees/recipes.doctree [new file with mode: 0644]
html/.doctrees/routing.doctree [new file with mode: 0644]
html/.doctrees/stpl.doctree [new file with mode: 0644]
html/.doctrees/tutorial.doctree [new file with mode: 0644]
html/.doctrees/tutorial_app.doctree [new file with mode: 0644]
html/_images/myface_small.png [new file with mode: 0644]
html/_modules/bottle.html [new file with mode: 0644]
html/_modules/index.html [new file with mode: 0644]
html/_sources/api.txt [new file with mode: 0644]
html/_sources/async.txt [new file with mode: 0644]
html/_sources/changelog.txt [new file with mode: 0644]
html/_sources/contact.txt [new file with mode: 0644]
html/_sources/deployment.txt [new file with mode: 0644]
html/_sources/development.txt [new file with mode: 0644]
html/_sources/faq.txt [new file with mode: 0644]
html/_sources/index.txt [new file with mode: 0644]
html/_sources/plugindev.txt [new file with mode: 0644]
html/_sources/plugins/index.txt [new file with mode: 0644]
html/_sources/plugins/sqlite.txt [new file with mode: 0644]
html/_sources/plugins/werkzeug.txt [new file with mode: 0644]
html/_sources/recipes.txt [new file with mode: 0644]
html/_sources/routing.txt [new file with mode: 0644]
html/_sources/stpl.txt [new file with mode: 0644]
html/_sources/tutorial.txt [new file with mode: 0644]
html/_sources/tutorial_app.txt [new file with mode: 0644]
html/_static/ajax-loader.gif [new file with mode: 0644]
html/_static/basic.css [new file with mode: 0644]
html/_static/bgrad.png [new file with mode: 0644]
html/_static/bottle.css [new file with mode: 0644]
html/_static/browser-example.png [new file with mode: 0644]
html/_static/comment-bright.png [new file with mode: 0644]
html/_static/comment-close.png [new file with mode: 0644]
html/_static/comment.png [new file with mode: 0644]
html/_static/default.css [new file with mode: 0644]
html/_static/default.js [new file with mode: 0644]
html/_static/doctools.js [new file with mode: 0644]
html/_static/down-pressed.png [new file with mode: 0644]
html/_static/down.png [new file with mode: 0644]
html/_static/favicon.ico [new file with mode: 0644]
html/_static/file.png [new file with mode: 0644]
html/_static/jquery.js [new file with mode: 0644]
html/_static/link_icon.png [new file with mode: 0644]
html/_static/logo_bg.png [new file with mode: 0644]
html/_static/logo_full.png [new file with mode: 0644]
html/_static/logo_icon.png [new file with mode: 0644]
html/_static/logo_nav.png [new file with mode: 0644]
html/_static/logo_reddit.png [new file with mode: 0644]
html/_static/minus.png [new file with mode: 0644]
html/_static/myface.png [new file with mode: 0644]
html/_static/myface_small.png [new file with mode: 0644]
html/_static/paypal.png [new file with mode: 0644]
html/_static/plus.png [new file with mode: 0644]
html/_static/pygments.css [new file with mode: 0644]
html/_static/searchtools.js [new file with mode: 0644]
html/_static/sidebar.js [new file with mode: 0644]
html/_static/underscore.js [new file with mode: 0644]
html/_static/up-pressed.png [new file with mode: 0644]
html/_static/up.png [new file with mode: 0644]
html/_static/websupport.js [new file with mode: 0644]
html/api.html [new file with mode: 0644]
html/async.html [new file with mode: 0644]
html/changelog.html [new file with mode: 0644]
html/contact.html [new file with mode: 0644]
html/deployment.html [new file with mode: 0644]
html/development.html [new file with mode: 0644]
html/faq.html [new file with mode: 0644]
html/genindex.html [new file with mode: 0644]
html/index.html [new file with mode: 0644]
html/objects.inv [new file with mode: 0644]
html/plugindev.html [new file with mode: 0644]
html/plugins/index.html [new file with mode: 0644]
html/plugins/sqlite.html [new file with mode: 0644]
html/plugins/werkzeug.html [new file with mode: 0644]
html/py-modindex.html [new file with mode: 0644]
html/recipes.html [new file with mode: 0644]
html/routing.html [new file with mode: 0644]
html/search.html [new file with mode: 0644]
html/searchindex.js [new file with mode: 0644]
html/stpl.html [new file with mode: 0644]
html/tutorial.html [new file with mode: 0644]
html/tutorial_app.html [new file with mode: 0644]

diff --git a/html/.buildinfo b/html/.buildinfo
new file mode 100644 (file)
index 0000000..e26ce06
--- /dev/null
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: ab131a67559bfa85a0c2739ac85f9423
+tags: fbb0d17656682115ca4d033fb2f83ba1
diff --git a/html/.doctrees/api.doctree b/html/.doctrees/api.doctree
new file mode 100644 (file)
index 0000000..b23196f
Binary files /dev/null and b/html/.doctrees/api.doctree differ
diff --git a/html/.doctrees/async.doctree b/html/.doctrees/async.doctree
new file mode 100644 (file)
index 0000000..487a200
Binary files /dev/null and b/html/.doctrees/async.doctree differ
diff --git a/html/.doctrees/changelog.doctree b/html/.doctrees/changelog.doctree
new file mode 100644 (file)
index 0000000..46caae3
Binary files /dev/null and b/html/.doctrees/changelog.doctree differ
diff --git a/html/.doctrees/contact.doctree b/html/.doctrees/contact.doctree
new file mode 100644 (file)
index 0000000..e7db5cd
Binary files /dev/null and b/html/.doctrees/contact.doctree differ
diff --git a/html/.doctrees/deployment.doctree b/html/.doctrees/deployment.doctree
new file mode 100644 (file)
index 0000000..31a8ef1
Binary files /dev/null and b/html/.doctrees/deployment.doctree differ
diff --git a/html/.doctrees/development.doctree b/html/.doctrees/development.doctree
new file mode 100644 (file)
index 0000000..6a6e5cf
Binary files /dev/null and b/html/.doctrees/development.doctree differ
diff --git a/html/.doctrees/environment.pickle b/html/.doctrees/environment.pickle
new file mode 100644 (file)
index 0000000..8cb65ac
Binary files /dev/null and b/html/.doctrees/environment.pickle differ
diff --git a/html/.doctrees/faq.doctree b/html/.doctrees/faq.doctree
new file mode 100644 (file)
index 0000000..e04db32
Binary files /dev/null and b/html/.doctrees/faq.doctree differ
diff --git a/html/.doctrees/index.doctree b/html/.doctrees/index.doctree
new file mode 100644 (file)
index 0000000..bf931f1
Binary files /dev/null and b/html/.doctrees/index.doctree differ
diff --git a/html/.doctrees/plugindev.doctree b/html/.doctrees/plugindev.doctree
new file mode 100644 (file)
index 0000000..979096b
Binary files /dev/null and b/html/.doctrees/plugindev.doctree differ
diff --git a/html/.doctrees/plugins/index.doctree b/html/.doctrees/plugins/index.doctree
new file mode 100644 (file)
index 0000000..92e6d0f
Binary files /dev/null and b/html/.doctrees/plugins/index.doctree differ
diff --git a/html/.doctrees/plugins/sqlite.doctree b/html/.doctrees/plugins/sqlite.doctree
new file mode 100644 (file)
index 0000000..0bad36f
Binary files /dev/null and b/html/.doctrees/plugins/sqlite.doctree differ
diff --git a/html/.doctrees/plugins/werkzeug.doctree b/html/.doctrees/plugins/werkzeug.doctree
new file mode 100644 (file)
index 0000000..c687bac
Binary files /dev/null and b/html/.doctrees/plugins/werkzeug.doctree differ
diff --git a/html/.doctrees/recipes.doctree b/html/.doctrees/recipes.doctree
new file mode 100644 (file)
index 0000000..7604494
Binary files /dev/null and b/html/.doctrees/recipes.doctree differ
diff --git a/html/.doctrees/routing.doctree b/html/.doctrees/routing.doctree
new file mode 100644 (file)
index 0000000..4e04a88
Binary files /dev/null and b/html/.doctrees/routing.doctree differ
diff --git a/html/.doctrees/stpl.doctree b/html/.doctrees/stpl.doctree
new file mode 100644 (file)
index 0000000..4cc2c27
Binary files /dev/null and b/html/.doctrees/stpl.doctree differ
diff --git a/html/.doctrees/tutorial.doctree b/html/.doctrees/tutorial.doctree
new file mode 100644 (file)
index 0000000..c6d43f1
Binary files /dev/null and b/html/.doctrees/tutorial.doctree differ
diff --git a/html/.doctrees/tutorial_app.doctree b/html/.doctrees/tutorial_app.doctree
new file mode 100644 (file)
index 0000000..d3573f8
Binary files /dev/null and b/html/.doctrees/tutorial_app.doctree differ
diff --git a/html/_images/myface_small.png b/html/_images/myface_small.png
new file mode 100644 (file)
index 0000000..24314f6
Binary files /dev/null and b/html/_images/myface_small.png differ
diff --git a/html/_modules/bottle.html b/html/_modules/bottle.html
new file mode 100644 (file)
index 0000000..5e9ea5c
--- /dev/null
@@ -0,0 +1,3408 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>bottle &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="../_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '../',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="../_static/jquery.js"></script>
+    <script type="text/javascript" src="../_static/underscore.js"></script>
+    <script type="text/javascript" src="../_static/doctools.js"></script>
+    <link rel="shortcut icon" href="../_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="../index.html" />
+    <link rel="up" title="Module code" href="index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="../_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="../_static/logo_reddit.png" />
+    <script type="application/javascript" src="../_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+
+          <li><a href="index.html" accesskey="U">Module code</a> &raquo;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <h1>Source code for bottle</h1><div class="highlight"><pre>
+<span class="c">#!/usr/bin/env python</span>
+<span class="c"># -*- coding: utf-8 -*-</span>
+<span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">Bottle is a fast and simple micro-framework for small web applications. It</span>
+<span class="sd">offers request dispatching (Routes) with url parameter support, templates,</span>
+<span class="sd">a built-in HTTP Server and adapters for many third party WSGI/HTTP-server and</span>
+<span class="sd">template engines - all in a single file and with no dependencies other than the</span>
+<span class="sd">Python Standard Library.</span>
+
+<span class="sd">Homepage and documentation: http://bottlepy.org/</span>
+
+<span class="sd">Copyright (c) 2012, Marcel Hellkamp.</span>
+<span class="sd">License: MIT (see LICENSE for details)</span>
+<span class="sd">&quot;&quot;&quot;</span>
+
+<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">with_statement</span>
+
+<span class="n">__author__</span> <span class="o">=</span> <span class="s">&#39;Marcel Hellkamp&#39;</span>
+<span class="n">__version__</span> <span class="o">=</span> <span class="s">&#39;0.12-dev&#39;</span>
+<span class="n">__license__</span> <span class="o">=</span> <span class="s">&#39;MIT&#39;</span>
+
+<span class="c"># The gevent server adapter needs to patch some modules before they are imported</span>
+<span class="c"># This is why we parse the commandline parameters here but handle them later</span>
+<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
+    <span class="kn">from</span> <span class="nn">optparse</span> <span class="kn">import</span> <span class="n">OptionParser</span>
+    <span class="n">_cmd_parser</span> <span class="o">=</span> <span class="n">OptionParser</span><span class="p">(</span><span class="n">usage</span><span class="o">=</span><span class="s">&quot;usage: %prog [options] package.module:app&quot;</span><span class="p">)</span>
+    <span class="n">_opt</span> <span class="o">=</span> <span class="n">_cmd_parser</span><span class="o">.</span><span class="n">add_option</span>
+    <span class="n">_opt</span><span class="p">(</span><span class="s">&quot;--version&quot;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">&quot;store_true&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;show version number.&quot;</span><span class="p">)</span>
+    <span class="n">_opt</span><span class="p">(</span><span class="s">&quot;-b&quot;</span><span class="p">,</span> <span class="s">&quot;--bind&quot;</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s">&quot;ADDRESS&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;bind socket to ADDRESS.&quot;</span><span class="p">)</span>
+    <span class="n">_opt</span><span class="p">(</span><span class="s">&quot;-s&quot;</span><span class="p">,</span> <span class="s">&quot;--server&quot;</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">&#39;wsgiref&#39;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;use SERVER as backend.&quot;</span><span class="p">)</span>
+    <span class="n">_opt</span><span class="p">(</span><span class="s">&quot;-p&quot;</span><span class="p">,</span> <span class="s">&quot;--plugin&quot;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">&quot;append&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;install additional plugin/s.&quot;</span><span class="p">)</span>
+    <span class="n">_opt</span><span class="p">(</span><span class="s">&quot;--debug&quot;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">&quot;store_true&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;start server in debug mode.&quot;</span><span class="p">)</span>
+    <span class="n">_opt</span><span class="p">(</span><span class="s">&quot;--reload&quot;</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">&quot;store_true&quot;</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">&quot;auto-reload on file changes.&quot;</span><span class="p">)</span>
+    <span class="n">_cmd_options</span><span class="p">,</span> <span class="n">_cmd_args</span> <span class="o">=</span> <span class="n">_cmd_parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span>
+    <span class="k">if</span> <span class="n">_cmd_options</span><span class="o">.</span><span class="n">server</span> <span class="ow">and</span> <span class="n">_cmd_options</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;gevent&#39;</span><span class="p">):</span>
+        <span class="kn">import</span> <span class="nn">gevent.monkey</span><span class="p">;</span> <span class="n">gevent</span><span class="o">.</span><span class="n">monkey</span><span class="o">.</span><span class="n">patch_all</span><span class="p">()</span>
+
+<span class="kn">import</span> <span class="nn">base64</span><span class="o">,</span> <span class="nn">cgi</span><span class="o">,</span> <span class="nn">email.utils</span><span class="o">,</span> <span class="nn">functools</span><span class="o">,</span> <span class="nn">hmac</span><span class="o">,</span> <span class="nn">imp</span><span class="o">,</span> <span class="nn">itertools</span><span class="o">,</span> <span class="nn">mimetypes</span><span class="o">,</span>\
+        <span class="n">os</span><span class="p">,</span> <span class="n">re</span><span class="p">,</span> <span class="n">subprocess</span><span class="p">,</span> <span class="n">sys</span><span class="p">,</span> <span class="n">tempfile</span><span class="p">,</span> <span class="n">threading</span><span class="p">,</span> <span class="n">time</span><span class="p">,</span> <span class="n">urllib</span><span class="p">,</span> <span class="n">warnings</span>
+
+<span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">date</span> <span class="k">as</span> <span class="n">datedate</span><span class="p">,</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span>
+<span class="kn">from</span> <span class="nn">tempfile</span> <span class="kn">import</span> <span class="n">TemporaryFile</span>
+<span class="kn">from</span> <span class="nn">traceback</span> <span class="kn">import</span> <span class="n">format_exc</span><span class="p">,</span> <span class="n">print_exc</span>
+
+<span class="k">try</span><span class="p">:</span> <span class="kn">from</span> <span class="nn">json</span> <span class="kn">import</span> <span class="n">dumps</span> <span class="k">as</span> <span class="n">json_dumps</span><span class="p">,</span> <span class="n">loads</span> <span class="k">as</span> <span class="n">json_lds</span>
+<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="c"># pragma: no cover</span>
+    <span class="k">try</span><span class="p">:</span> <span class="kn">from</span> <span class="nn">simplejson</span> <span class="kn">import</span> <span class="n">dumps</span> <span class="k">as</span> <span class="n">json_dumps</span><span class="p">,</span> <span class="n">loads</span> <span class="k">as</span> <span class="n">json_lds</span>
+    <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
+        <span class="k">try</span><span class="p">:</span> <span class="kn">from</span> <span class="nn">django.utils.simplejson</span> <span class="kn">import</span> <span class="n">dumps</span> <span class="k">as</span> <span class="n">json_dumps</span><span class="p">,</span> <span class="n">loads</span> <span class="k">as</span> <span class="n">json_lds</span>
+        <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
+            <span class="k">def</span> <span class="nf">json_dumps</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
+                <span class="k">raise</span> <span class="ne">ImportError</span><span class="p">(</span><span class="s">&quot;JSON support requires Python 2.6 or simplejson.&quot;</span><span class="p">)</span>
+            <span class="n">json_lds</span> <span class="o">=</span> <span class="n">json_dumps</span>
+
+
+
+<span class="c"># We now try to fix 2.5/2.6/3.1/3.2 incompatibilities.</span>
+<span class="c"># It ain&#39;t pretty but it works... Sorry for the mess.</span>
+
+<span class="n">py</span>   <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span>
+<span class="n">py3k</span> <span class="o">=</span> <span class="n">py</span> <span class="o">&gt;=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span>
+<span class="n">py25</span> <span class="o">=</span> <span class="n">py</span> <span class="o">&lt;</span>  <span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span>
+<span class="n">py31</span> <span class="o">=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="n">py</span> <span class="o">&lt;</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span>
+
+<span class="c"># Workaround for the missing &quot;as&quot; keyword in py3k.</span>
+<span class="k">def</span> <span class="nf">_e</span><span class="p">():</span> <span class="k">return</span> <span class="n">sys</span><span class="o">.</span><span class="n">exc_info</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>
+
+<span class="c"># Workaround for the &quot;print is a keyword/function&quot; Python 2/3 dilemma</span>
+<span class="c"># and a fallback for mod_wsgi (resticts stdout/err attribute access)</span>
+<span class="k">try</span><span class="p">:</span>
+    <span class="n">_stdout</span><span class="p">,</span> <span class="n">_stderr</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span>
+<span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
+    <span class="n">_stdout</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
+    <span class="n">_stderr</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
+
+<span class="c"># Lots of stdlib and builtin differences.</span>
+<span class="k">if</span> <span class="n">py3k</span><span class="p">:</span>
+    <span class="kn">import</span> <span class="nn">http.client</span> <span class="kn">as</span> <span class="nn">httplib</span>
+    <span class="kn">import</span> <span class="nn">_thread</span> <span class="kn">as</span> <span class="nn">thread</span>
+    <span class="kn">from</span> <span class="nn">urllib.parse</span> <span class="kn">import</span> <span class="n">urljoin</span><span class="p">,</span> <span class="n">SplitResult</span> <span class="k">as</span> <span class="n">UrlSplitResult</span>
+    <span class="kn">from</span> <span class="nn">urllib.parse</span> <span class="kn">import</span> <span class="n">urlencode</span><span class="p">,</span> <span class="n">quote</span> <span class="k">as</span> <span class="n">urlquote</span><span class="p">,</span> <span class="n">unquote</span> <span class="k">as</span> <span class="n">urlunquote</span>
+    <span class="n">urlunquote</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">urlunquote</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s">&#39;latin1&#39;</span><span class="p">)</span>
+    <span class="kn">from</span> <span class="nn">http.cookies</span> <span class="kn">import</span> <span class="n">SimpleCookie</span>
+    <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">MutableMapping</span> <span class="k">as</span> <span class="n">DictMixin</span>
+    <span class="kn">import</span> <span class="nn">pickle</span>
+    <span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">BytesIO</span>
+    <span class="nb">basestring</span> <span class="o">=</span> <span class="nb">str</span>
+    <span class="nb">unicode</span> <span class="o">=</span> <span class="nb">str</span>
+    <span class="n">json_loads</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="n">json_lds</span><span class="p">(</span><span class="n">touni</span><span class="p">(</span><span class="n">s</span><span class="p">))</span>
+    <span class="nb">callable</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="s">&#39;__call__&#39;</span><span class="p">)</span>
+    <span class="n">imap</span> <span class="o">=</span> <span class="nb">map</span>
+<span class="k">else</span><span class="p">:</span> <span class="c"># 2.x</span>
+    <span class="kn">import</span> <span class="nn">httplib</span>
+    <span class="kn">import</span> <span class="nn">thread</span>
+    <span class="kn">from</span> <span class="nn">urlparse</span> <span class="kn">import</span> <span class="n">urljoin</span><span class="p">,</span> <span class="n">SplitResult</span> <span class="k">as</span> <span class="n">UrlSplitResult</span>
+    <span class="kn">from</span> <span class="nn">urllib</span> <span class="kn">import</span> <span class="n">urlencode</span><span class="p">,</span> <span class="n">quote</span> <span class="k">as</span> <span class="n">urlquote</span><span class="p">,</span> <span class="n">unquote</span> <span class="k">as</span> <span class="n">urlunquote</span>
+    <span class="kn">from</span> <span class="nn">Cookie</span> <span class="kn">import</span> <span class="n">SimpleCookie</span>
+    <span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">imap</span>
+    <span class="kn">import</span> <span class="nn">cPickle</span> <span class="kn">as</span> <span class="nn">pickle</span>
+    <span class="kn">from</span> <span class="nn">StringIO</span> <span class="kn">import</span> <span class="n">StringIO</span> <span class="k">as</span> <span class="n">BytesIO</span>
+    <span class="k">if</span> <span class="n">py25</span><span class="p">:</span>
+        <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Python 2.5 support may be dropped in future versions of Bottle.&quot;</span>
+        <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="n">msg</span><span class="p">,</span> <span class="ne">DeprecationWarning</span><span class="p">)</span>
+        <span class="kn">from</span> <span class="nn">UserDict</span> <span class="kn">import</span> <span class="n">DictMixin</span>
+        <span class="k">def</span> <span class="nf">next</span><span class="p">(</span><span class="n">it</span><span class="p">):</span> <span class="k">return</span> <span class="n">it</span><span class="o">.</span><span class="n">next</span><span class="p">()</span>
+        <span class="nb">bytes</span> <span class="o">=</span> <span class="nb">str</span>
+    <span class="k">else</span><span class="p">:</span> <span class="c"># 2.6, 2.7</span>
+        <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">MutableMapping</span> <span class="k">as</span> <span class="n">DictMixin</span>
+    <span class="n">json_loads</span> <span class="o">=</span> <span class="n">json_lds</span>
+
+<span class="c"># Some helpers for string/byte handling</span>
+<span class="k">def</span> <span class="nf">tob</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">enc</span><span class="o">=</span><span class="s">&#39;utf8&#39;</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">enc</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)</span> <span class="k">else</span> <span class="nb">bytes</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">touni</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">enc</span><span class="o">=</span><span class="s">&#39;utf8&#39;</span><span class="p">,</span> <span class="n">err</span><span class="o">=</span><span class="s">&#39;strict&#39;</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="n">enc</span><span class="p">,</span> <span class="n">err</span><span class="p">)</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)</span> <span class="k">else</span> <span class="nb">unicode</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
+<span class="n">tonat</span> <span class="o">=</span> <span class="n">touni</span> <span class="k">if</span> <span class="n">py3k</span> <span class="k">else</span> <span class="n">tob</span>
+
+<span class="c"># 3.2 fixes cgi.FieldStorage to accept bytes (which makes a lot of sense).</span>
+<span class="c"># 3.1 needs a workaround.</span>
+<span class="k">if</span> <span class="n">py31</span><span class="p">:</span>
+    <span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">TextIOWrapper</span>
+    <span class="k">class</span> <span class="nc">NCTextIOWrapper</span><span class="p">(</span><span class="n">TextIOWrapper</span><span class="p">):</span>
+        <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</span> <span class="c"># Keep wrapped buffer open.</span>
+
+<span class="c"># File uploads (which are implemented as empty FiledStorage instances...)</span>
+<span class="c"># have a negative truth value. That makes no sense, here is a fix.</span>
+<span class="k">class</span> <span class="nc">FieldStorage</span><span class="p">(</span><span class="n">cgi</span><span class="o">.</span><span class="n">FieldStorage</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">__nonzero__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">list</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">file</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">py3k</span><span class="p">:</span> <span class="n">__bool__</span> <span class="o">=</span> <span class="n">__nonzero__</span>
+
+<span class="c"># A bug in functools causes it to break if the wrapper is an instance method</span>
+<span class="k">def</span> <span class="nf">update_wrapper</span><span class="p">(</span><span class="n">wrapper</span><span class="p">,</span> <span class="n">wrapped</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+    <span class="k">try</span><span class="p">:</span> <span class="n">functools</span><span class="o">.</span><span class="n">update_wrapper</span><span class="p">(</span><span class="n">wrapper</span><span class="p">,</span> <span class="n">wrapped</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+    <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span> <span class="k">pass</span>
+
+
+
+<span class="c"># These helpers are used at module level and need to be defined first.</span>
+<span class="c"># And yes, I know PEP-8, but sometimes a lower-case classname makes more sense.</span>
+
+<span class="k">def</span> <span class="nf">depr</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
+    <span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="ne">DeprecationWarning</span><span class="p">,</span> <span class="n">stacklevel</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
+
+<span class="k">def</span> <span class="nf">makelist</span><span class="p">(</span><span class="n">data</span><span class="p">):</span> <span class="c"># This is just to handy</span>
+    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">,</span> <span class="nb">set</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)):</span> <span class="k">return</span> <span class="nb">list</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
+    <span class="k">elif</span> <span class="n">data</span><span class="p">:</span> <span class="k">return</span> <span class="p">[</span><span class="n">data</span><span class="p">]</span>
+    <span class="k">else</span><span class="p">:</span> <span class="k">return</span> <span class="p">[]</span>
+
+
+<span class="k">class</span> <span class="nc">DictProperty</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Property that maps to a key in a local dict-like attribute. &#39;&#39;&#39;</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">attr</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">read_only</span> <span class="o">=</span> <span class="n">attr</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">read_only</span>
+
+    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
+        <span class="n">functools</span><span class="o">.</span><span class="n">update_wrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">updated</span><span class="o">=</span><span class="p">[])</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">getter</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">func</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="ow">or</span> <span class="n">func</span><span class="o">.</span><span class="n">__name__</span>
+        <span class="k">return</span> <span class="bp">self</span>
+
+    <span class="k">def</span> <span class="nf">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">cls</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span>
+        <span class="n">key</span><span class="p">,</span> <span class="n">storage</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">attr</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">storage</span><span class="p">:</span> <span class="n">storage</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">getter</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">storage</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
+
+    <span class="k">def</span> <span class="nf">__set__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">read_only</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s">&quot;Read-Only property.&quot;</span><span class="p">)</span>
+        <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">attr</span><span class="p">)[</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+
+    <span class="k">def</span> <span class="nf">__delete__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">read_only</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s">&quot;Read-Only property.&quot;</span><span class="p">)</span>
+        <span class="k">del</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">attr</span><span class="p">)[</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">]</span>
+
+
+<span class="k">class</span> <span class="nc">cached_property</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; A property that is only computed once per instance and then replaces</span>
+<span class="sd">        itself with an ordinary attribute. Deleting the attribute resets the</span>
+<span class="sd">        property. &#39;&#39;&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">func</span> <span class="o">=</span> <span class="n">func</span>
+
+    <span class="k">def</span> <span class="nf">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">cls</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span>
+        <span class="n">value</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">__dict__</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">func</span><span class="o">.</span><span class="n">__name__</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">func</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">value</span>
+
+
+<span class="k">class</span> <span class="nc">lazy_attribute</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; A property that caches itself to the class object. &#39;&#39;&#39;</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
+        <span class="n">functools</span><span class="o">.</span><span class="n">update_wrapper</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">func</span><span class="p">,</span> <span class="n">updated</span><span class="o">=</span><span class="p">[])</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">getter</span> <span class="o">=</span> <span class="n">func</span>
+
+    <span class="k">def</span> <span class="nf">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">cls</span><span class="p">):</span>
+        <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">getter</span><span class="p">(</span><span class="n">cls</span><span class="p">)</span>
+        <span class="nb">setattr</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">value</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Exceptions and Events ########################################################</span>
+<span class="c">###############################################################################</span>
+
+
+<div class="viewcode-block" id="BottleException"><a class="viewcode-back" href="../api.html#bottle.BottleException">[docs]</a><span class="k">class</span> <span class="nc">BottleException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; A base class for exceptions used by bottle. &quot;&quot;&quot;</span>
+    <span class="k">pass</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Routing ######################################################################</span>
+<span class="c">###############################################################################</span>
+
+</div>
+<span class="k">class</span> <span class="nc">RouteError</span><span class="p">(</span><span class="n">BottleException</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; This is a base class for all routing related exceptions &quot;&quot;&quot;</span>
+
+
+<span class="k">class</span> <span class="nc">RouteReset</span><span class="p">(</span><span class="n">BottleException</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; If raised by a plugin or request handler, the route is reset and all</span>
+<span class="sd">        plugins are re-applied. &quot;&quot;&quot;</span>
+
+<span class="k">class</span> <span class="nc">RouterUnknownModeError</span><span class="p">(</span><span class="n">RouteError</span><span class="p">):</span> <span class="k">pass</span>
+
+
+<span class="k">class</span> <span class="nc">RouteSyntaxError</span><span class="p">(</span><span class="n">RouteError</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; The route parser found something not supported by this router &quot;&quot;&quot;</span>
+
+
+<span class="k">class</span> <span class="nc">RouteBuildError</span><span class="p">(</span><span class="n">RouteError</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; The route could not been built &quot;&quot;&quot;</span>
+
+
+<span class="k">class</span> <span class="nc">Router</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; A Router is an ordered collection of route-&gt;target pairs. It is used to</span>
+<span class="sd">        efficiently match WSGI requests against a number of routes and return</span>
+<span class="sd">        the first target that satisfies the request. The target may be anything,</span>
+<span class="sd">        usually a string, ID or callable object. A route consists of a path-rule</span>
+<span class="sd">        and a HTTP method.</span>
+
+<span class="sd">        The path-rule is either a static path (e.g. `/contact`) or a dynamic</span>
+<span class="sd">        path that contains wildcards (e.g. `/wiki/&lt;page&gt;`). The wildcard syntax</span>
+<span class="sd">        and details on the matching order are described in docs:`routing`.</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+
+    <span class="n">default_pattern</span> <span class="o">=</span> <span class="s">&#39;[^/]+&#39;</span>
+    <span class="n">default_filter</span>   <span class="o">=</span> <span class="s">&#39;re&#39;</span>
+    <span class="c">#: Sorry for the mess. It works. Trust me.</span>
+    <span class="n">rule_syntax</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;(</span><span class="se">\\\\</span><span class="s">*)&#39;</span>\
+        <span class="s">&#39;(?:(?::([a-zA-Z_][a-zA-Z_0-9]*)?()(?:#(.*?)#)?)&#39;</span>\
+          <span class="s">&#39;|(?:&lt;([a-zA-Z_][a-zA-Z_0-9]*)?(?::([a-zA-Z_]*)&#39;</span>\
+            <span class="s">&#39;(?::((?:</span><span class="se">\\\\</span><span class="s">.|[^</span><span class="se">\\\\</span><span class="s">&gt;]+)+)?)?)?&gt;))&#39;</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">rules</span>    <span class="o">=</span> <span class="p">{}</span> <span class="c"># A {rule: Rule} mapping</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">builder</span>  <span class="o">=</span> <span class="p">{}</span> <span class="c"># A rule/name-&gt;build_info mapping</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">static</span>   <span class="o">=</span> <span class="p">{}</span> <span class="c"># Cache for static routes: {path: {method: target}}</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span>  <span class="o">=</span> <span class="p">[]</span> <span class="c"># Cache for dynamic routes. See _compile()</span>
+        <span class="c">#: If true, static routes are no longer checked first.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">strict_order</span> <span class="o">=</span> <span class="n">strict</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">filters</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;re&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">re_filter</span><span class="p">,</span> <span class="s">&#39;int&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">int_filter</span><span class="p">,</span>
+                        <span class="s">&#39;float&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">float_filter</span><span class="p">,</span> <span class="s">&#39;path&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">path_filter</span><span class="p">}</span>
+
+    <span class="k">def</span> <span class="nf">re_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conf</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">conf</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_pattern</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>
+
+    <span class="k">def</span> <span class="nf">int_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conf</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">r&#39;-?\d+&#39;</span><span class="p">,</span> <span class="nb">int</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
+
+    <span class="k">def</span> <span class="nf">float_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conf</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">r&#39;-?[\d.]+&#39;</span><span class="p">,</span> <span class="nb">float</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="nb">float</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
+
+    <span class="k">def</span> <span class="nf">path_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conf</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">r&#39;.+?&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>
+
+    <span class="k">def</span> <span class="nf">add_filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add a filter. The provided function is called with the configuration</span>
+<span class="sd">        string as parameter and must return a (regexp, to_python, to_url) tuple.</span>
+<span class="sd">        The first element is a string, the last two are callables or None. &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">func</span>
+
+    <span class="k">def</span> <span class="nf">parse_rule</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rule</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Parses a rule into a (name, filter, conf) token stream. If mode is</span>
+<span class="sd">            None, name contains a static rule part. &#39;&#39;&#39;</span>
+        <span class="n">offset</span><span class="p">,</span> <span class="n">prefix</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="s">&#39;&#39;</span>
+        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">rule_syntax</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
+            <span class="n">prefix</span> <span class="o">+=</span> <span class="n">rule</span><span class="p">[</span><span class="n">offset</span><span class="p">:</span><span class="n">match</span><span class="o">.</span><span class="n">start</span><span class="p">()]</span>
+            <span class="n">g</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
+            <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="o">%</span><span class="mi">2</span><span class="p">:</span> <span class="c"># Escaped wildcard</span>
+                <span class="n">prefix</span> <span class="o">+=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)[</span><span class="nb">len</span><span class="p">(</span><span class="n">g</span><span class="p">[</span><span class="mi">0</span><span class="p">]):]</span>
+                <span class="n">offset</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">()</span>
+                <span class="k">continue</span>
+            <span class="k">if</span> <span class="n">prefix</span><span class="p">:</span> <span class="k">yield</span> <span class="n">prefix</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>
+            <span class="n">name</span><span class="p">,</span> <span class="n">filtr</span><span class="p">,</span> <span class="n">conf</span> <span class="o">=</span> <span class="n">g</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">4</span><span class="p">]</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">g</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="ow">is</span> <span class="bp">None</span> <span class="k">else</span> <span class="n">g</span><span class="p">[</span><span class="mi">4</span><span class="p">:</span><span class="mi">7</span><span class="p">]</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">filtr</span><span class="p">:</span> <span class="n">filtr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_filter</span>
+            <span class="k">yield</span> <span class="n">name</span><span class="p">,</span> <span class="n">filtr</span><span class="p">,</span> <span class="n">conf</span> <span class="ow">or</span> <span class="bp">None</span>
+            <span class="n">offset</span><span class="p">,</span> <span class="n">prefix</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">end</span><span class="p">(),</span> <span class="s">&#39;&#39;</span>
+        <span class="k">if</span> <span class="n">offset</span> <span class="o">&lt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">rule</span><span class="p">)</span> <span class="ow">or</span> <span class="n">prefix</span><span class="p">:</span>
+            <span class="k">yield</span> <span class="n">prefix</span><span class="o">+</span><span class="n">rule</span><span class="p">[</span><span class="n">offset</span><span class="p">:],</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>
+
+    <span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rule</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">target</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add a new route or replace the target for an existing route. &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="n">rule</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">[</span><span class="n">rule</span><span class="p">][</span><span class="n">method</span><span class="p">]</span> <span class="o">=</span> <span class="n">target</span>
+            <span class="k">if</span> <span class="n">name</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">builder</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">builder</span><span class="p">[</span><span class="n">rule</span><span class="p">]</span>
+            <span class="k">return</span>
+
+        <span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">rules</span><span class="p">[</span><span class="n">rule</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">method</span><span class="p">:</span> <span class="n">target</span><span class="p">}</span>
+
+        <span class="c"># Build pattern and other structures for dynamic routes</span>
+        <span class="n">anons</span> <span class="o">=</span> <span class="mi">0</span>      <span class="c"># Number of anonymous wildcards</span>
+        <span class="n">pattern</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>   <span class="c"># Regular expression  pattern</span>
+        <span class="n">filters</span> <span class="o">=</span> <span class="p">[]</span>   <span class="c"># Lists of wildcard input filters</span>
+        <span class="n">builder</span> <span class="o">=</span> <span class="p">[]</span>   <span class="c"># Data structure for the URL builder</span>
+        <span class="n">is_static</span> <span class="o">=</span> <span class="bp">True</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">mode</span><span class="p">,</span> <span class="n">conf</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">parse_rule</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
+            <span class="k">if</span> <span class="n">mode</span><span class="p">:</span>
+                <span class="n">is_static</span> <span class="o">=</span> <span class="bp">False</span>
+                <span class="n">mask</span><span class="p">,</span> <span class="n">in_filter</span><span class="p">,</span> <span class="n">out_filter</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">filters</span><span class="p">[</span><span class="n">mode</span><span class="p">](</span><span class="n">conf</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">key</span><span class="p">:</span>
+                    <span class="n">pattern</span> <span class="o">+=</span> <span class="s">&#39;(?P&lt;</span><span class="si">%s</span><span class="s">&gt;</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">mask</span><span class="p">)</span>
+                <span class="k">else</span><span class="p">:</span>
+                    <span class="n">pattern</span> <span class="o">+=</span> <span class="s">&#39;(?:</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="n">mask</span>
+                    <span class="n">key</span> <span class="o">=</span> <span class="s">&#39;anon</span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">anons</span><span class="p">;</span> <span class="n">anons</span> <span class="o">+=</span> <span class="mi">1</span>
+                <span class="k">if</span> <span class="n">in_filter</span><span class="p">:</span> <span class="n">filters</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">key</span><span class="p">,</span> <span class="n">in_filter</span><span class="p">))</span>
+                <span class="n">builder</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">key</span><span class="p">,</span> <span class="n">out_filter</span> <span class="ow">or</span> <span class="nb">str</span><span class="p">))</span>
+            <span class="k">elif</span> <span class="n">key</span><span class="p">:</span>
+                <span class="n">pattern</span> <span class="o">+=</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
+                <span class="n">builder</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="bp">None</span><span class="p">,</span> <span class="n">key</span><span class="p">))</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">builder</span><span class="p">[</span><span class="n">rule</span><span class="p">]</span> <span class="o">=</span> <span class="n">builder</span>
+        <span class="k">if</span> <span class="n">name</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">builder</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">builder</span>
+
+        <span class="k">if</span> <span class="n">is_static</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">strict_order</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">static</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">build</span><span class="p">(</span><span class="n">rule</span><span class="p">)]</span> <span class="o">=</span> <span class="n">target</span>
+            <span class="k">return</span>
+
+        <span class="k">def</span> <span class="nf">fpat_sub</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
+            <span class="k">return</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="o">%</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;(?:&#39;</span>
+        <span class="n">flat_pattern</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="s">r&#39;(</span><span class="se">\\</span><span class="s">*)(\(\?P&lt;[^&gt;]*&gt;|\((?!\?))&#39;</span><span class="p">,</span> <span class="n">fpat_sub</span><span class="p">,</span> <span class="n">pattern</span><span class="p">)</span>
+
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">re_match</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;^(</span><span class="si">%s</span><span class="s">)$&#39;</span> <span class="o">%</span> <span class="n">pattern</span><span class="p">)</span><span class="o">.</span><span class="n">match</span>
+        <span class="k">except</span> <span class="n">re</span><span class="o">.</span><span class="n">error</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="n">RouteSyntaxError</span><span class="p">(</span><span class="s">&quot;Could not add Route: </span><span class="si">%s</span><span class="s"> (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="n">_e</span><span class="p">()))</span>
+
+        <span class="k">def</span> <span class="nf">match</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+            <span class="sd">&quot;&quot;&quot; Return an url-argument dictionary. &quot;&quot;&quot;</span>
+            <span class="n">url_args</span> <span class="o">=</span> <span class="n">re_match</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="o">.</span><span class="n">groupdict</span><span class="p">()</span>
+            <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">wildcard_filter</span> <span class="ow">in</span> <span class="n">filters</span><span class="p">:</span>
+                <span class="k">try</span><span class="p">:</span>
+                    <span class="n">url_args</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">wildcard_filter</span><span class="p">(</span><span class="n">url_args</span><span class="p">[</span><span class="n">name</span><span class="p">])</span>
+                <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
+                    <span class="k">raise</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="s">&#39;Path has wrong format.&#39;</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">url_args</span>
+
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">combined</span> <span class="o">=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">|(^</span><span class="si">%s</span><span class="s">$)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">pattern</span><span class="p">,</span> <span class="n">flat_pattern</span><span class="p">)</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">combined</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">match</span><span class="p">,</span> <span class="n">target</span><span class="p">))</span>
+        <span class="k">except</span> <span class="p">(</span><span class="ne">AssertionError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">):</span> <span class="c"># AssertionError: Too many groups</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;(^</span><span class="si">%s</span><span class="s">$)&#39;</span> <span class="o">%</span> <span class="n">flat_pattern</span><span class="p">),</span>
+                                <span class="p">[(</span><span class="n">match</span><span class="p">,</span> <span class="n">target</span><span class="p">)]))</span>
+        <span class="k">return</span> <span class="n">match</span>
+
+    <span class="k">def</span> <span class="nf">build</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_name</span><span class="p">,</span> <span class="o">*</span><span class="n">anons</span><span class="p">,</span> <span class="o">**</span><span class="n">query</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Build an URL by filling the wildcards in a rule. &#39;&#39;&#39;</span>
+        <span class="n">builder</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">builder</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_name</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">builder</span><span class="p">:</span> <span class="k">raise</span> <span class="n">RouteBuildError</span><span class="p">(</span><span class="s">&quot;No route with that name.&quot;</span><span class="p">,</span> <span class="n">_name</span><span class="p">)</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">anons</span><span class="p">):</span> <span class="n">query</span><span class="p">[</span><span class="s">&#39;anon</span><span class="si">%d</span><span class="s">&#39;</span><span class="o">%</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+            <span class="n">url</span> <span class="o">=</span> <span class="s">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">f</span><span class="p">(</span><span class="n">query</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">n</span><span class="p">))</span> <span class="k">if</span> <span class="n">n</span> <span class="k">else</span> <span class="n">f</span> <span class="k">for</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="n">f</span><span class="p">)</span> <span class="ow">in</span> <span class="n">builder</span><span class="p">])</span>
+            <span class="k">return</span> <span class="n">url</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span> <span class="k">else</span> <span class="n">url</span><span class="o">+</span><span class="s">&#39;?&#39;</span><span class="o">+</span><span class="n">urlencode</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
+        <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="n">RouteBuildError</span><span class="p">(</span><span class="s">&#39;Missing URL argument: </span><span class="si">%r</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">_e</span><span class="p">()</span><span class="o">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
+
+    <span class="k">def</span> <span class="nf">match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Return a (target, url_agrs) tuple or raise HTTPError(400/404/405). &#39;&#39;&#39;</span>
+        <span class="n">path</span><span class="p">,</span> <span class="n">targets</span><span class="p">,</span> <span class="n">urlargs</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="ow">or</span> <span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="p">{}</span>
+        <span class="k">if</span> <span class="n">path</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">static</span><span class="p">:</span>
+            <span class="n">targets</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">static</span><span class="p">[</span><span class="n">path</span><span class="p">]</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">combined</span><span class="p">,</span> <span class="n">rules</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dynamic</span><span class="p">:</span>
+                <span class="n">match</span> <span class="o">=</span> <span class="n">combined</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+                <span class="k">if</span> <span class="ow">not</span> <span class="n">match</span><span class="p">:</span> <span class="k">continue</span>
+                <span class="n">getargs</span><span class="p">,</span> <span class="n">targets</span> <span class="o">=</span> <span class="n">rules</span><span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">lastindex</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
+                <span class="n">urlargs</span> <span class="o">=</span> <span class="n">getargs</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="k">if</span> <span class="n">getargs</span> <span class="k">else</span> <span class="p">{}</span>
+                <span class="k">break</span>
+
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">targets</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="s">&quot;Not found: &quot;</span> <span class="o">+</span> <span class="nb">repr</span><span class="p">(</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]))</span>
+        <span class="n">method</span> <span class="o">=</span> <span class="n">environ</span><span class="p">[</span><span class="s">&#39;REQUEST_METHOD&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
+        <span class="k">if</span> <span class="n">method</span> <span class="ow">in</span> <span class="n">targets</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">targets</span><span class="p">[</span><span class="n">method</span><span class="p">],</span> <span class="n">urlargs</span>
+        <span class="k">if</span> <span class="n">method</span> <span class="o">==</span> <span class="s">&#39;HEAD&#39;</span> <span class="ow">and</span> <span class="s">&#39;GET&#39;</span> <span class="ow">in</span> <span class="n">targets</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">targets</span><span class="p">[</span><span class="s">&#39;GET&#39;</span><span class="p">],</span> <span class="n">urlargs</span>
+        <span class="k">if</span> <span class="s">&#39;ANY&#39;</span> <span class="ow">in</span> <span class="n">targets</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">targets</span><span class="p">[</span><span class="s">&#39;ANY&#39;</span><span class="p">],</span> <span class="n">urlargs</span>
+        <span class="n">allowed</span> <span class="o">=</span> <span class="p">[</span><span class="n">verb</span> <span class="k">for</span> <span class="n">verb</span> <span class="ow">in</span> <span class="n">targets</span> <span class="k">if</span> <span class="n">verb</span> <span class="o">!=</span> <span class="s">&#39;ANY&#39;</span><span class="p">]</span>
+        <span class="k">if</span> <span class="s">&#39;GET&#39;</span> <span class="ow">in</span> <span class="n">allowed</span> <span class="ow">and</span> <span class="s">&#39;HEAD&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">allowed</span><span class="p">:</span>
+            <span class="n">allowed</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;HEAD&#39;</span><span class="p">)</span>
+        <span class="k">raise</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">405</span><span class="p">,</span> <span class="s">&quot;Method not allowed.&quot;</span><span class="p">,</span> <span class="n">Allow</span><span class="o">=</span><span class="s">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">allowed</span><span class="p">))</span>
+
+
+<div class="viewcode-block" id="Route"><a class="viewcode-back" href="../api.html#bottle.Route">[docs]</a><span class="k">class</span> <span class="nc">Route</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; This class wraps a route callback along with route specific metadata and</span>
+<span class="sd">        configuration and applies Plugins on demand. It is also responsible for</span>
+<span class="sd">        turing an URL path rule into a regular expression usable by the Router.</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">,</span> <span class="n">rule</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
+                 <span class="n">plugins</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">skiplist</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+        <span class="c">#: The application this route is installed to.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
+        <span class="c">#: The path-rule string (e.g. ``/wiki/:page``).</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">rule</span> <span class="o">=</span> <span class="n">rule</span>
+        <span class="c">#: The HTTP method as a string (e.g. ``GET``).</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">method</span>
+        <span class="c">#: The original callback with no plugins applied. Useful for introspection.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">callback</span> <span class="o">=</span> <span class="n">callback</span>
+        <span class="c">#: The name of the route (if specified) or ``None``.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="ow">or</span> <span class="bp">None</span>
+        <span class="c">#: A list of route-specific plugins (see :meth:`Bottle.route`).</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">plugins</span> <span class="o">=</span> <span class="n">plugins</span> <span class="ow">or</span> <span class="p">[]</span>
+        <span class="c">#: A list of plugins to not apply to this route (see :meth:`Bottle.route`).</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">skiplist</span> <span class="o">=</span> <span class="n">skiplist</span> <span class="ow">or</span> <span class="p">[]</span>
+        <span class="c">#: Additional keyword arguments passed to the :meth:`Bottle.route`</span>
+        <span class="c">#: decorator are stored in this dictionary. Used for route-specific</span>
+        <span class="c">#: plugin configuration and meta-data.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">config</span> <span class="o">=</span> <span class="n">ConfigDict</span><span class="p">(</span><span class="n">config</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&quot;Some APIs changed to return Route() instances instead of&quot;</span>\
+             <span class="s">&quot; callables. Make sure to use the Route.call method and not to&quot;</span>\
+             <span class="s">&quot; call Route instances directly.&quot;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+
+    <span class="nd">@cached_property</span>
+    <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The route callback with all plugins applied. This property is</span>
+<span class="sd">            created on demand and then cached to speed up subsequent requests.&#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_callback</span><span class="p">()</span>
+
+<div class="viewcode-block" id="Route.reset"><a class="viewcode-back" href="../api.html#bottle.Route.reset">[docs]</a>    <span class="k">def</span> <span class="nf">reset</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Forget any cached values. The next time :attr:`call` is accessed,</span>
+<span class="sd">            all plugins are re-applied. &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">__dict__</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;call&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Route.prepare"><a class="viewcode-back" href="../api.html#bottle.Route.prepare">[docs]</a>    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Do all on-demand work immediately (useful for debugging).&#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">call</span>
+</div>
+    <span class="nd">@property</span>
+    <span class="k">def</span> <span class="nf">_context</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&#39;Switch to Plugin API v2 and access the Route object directly.&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">rule</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">rule</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">,</span>
+                    <span class="n">name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">app</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="p">,</span> <span class="n">config</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="p">,</span>
+                    <span class="nb">apply</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">plugins</span><span class="p">,</span> <span class="n">skip</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">skiplist</span><span class="p">)</span>
+
+<div class="viewcode-block" id="Route.all_plugins"><a class="viewcode-back" href="../api.html#bottle.Route.all_plugins">[docs]</a>    <span class="k">def</span> <span class="nf">all_plugins</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Yield all Plugins affecting this route. &#39;&#39;&#39;</span>
+        <span class="n">unique</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
+        <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">plugins</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">plugins</span><span class="p">):</span>
+            <span class="k">if</span> <span class="bp">True</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">skiplist</span><span class="p">:</span> <span class="k">break</span>
+            <span class="n">name</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="s">&#39;name&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">name</span> <span class="ow">and</span> <span class="p">(</span><span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">skiplist</span> <span class="ow">or</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">unique</span><span class="p">):</span> <span class="k">continue</span>
+            <span class="k">if</span> <span class="n">p</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">skiplist</span> <span class="ow">or</span> <span class="nb">type</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">skiplist</span><span class="p">:</span> <span class="k">continue</span>
+            <span class="k">if</span> <span class="n">name</span><span class="p">:</span> <span class="n">unique</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+            <span class="k">yield</span> <span class="n">p</span>
+</div>
+    <span class="k">def</span> <span class="nf">_make_callback</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">callback</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback</span>
+        <span class="k">for</span> <span class="n">plugin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">all_plugins</span><span class="p">():</span>
+            <span class="k">try</span><span class="p">:</span>
+                <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;apply&#39;</span><span class="p">):</span>
+                    <span class="n">api</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;api&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+                    <span class="n">context</span> <span class="o">=</span> <span class="bp">self</span> <span class="k">if</span> <span class="n">api</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="k">else</span> <span class="bp">self</span><span class="o">.</span><span class="n">_context</span>
+                    <span class="n">callback</span> <span class="o">=</span> <span class="n">plugin</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="n">context</span><span class="p">)</span>
+                <span class="k">else</span><span class="p">:</span>
+                    <span class="n">callback</span> <span class="o">=</span> <span class="n">plugin</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span>
+            <span class="k">except</span> <span class="n">RouteReset</span><span class="p">:</span> <span class="c"># Try again with changed configuration.</span>
+                <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_callback</span><span class="p">()</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">callback</span> <span class="ow">is</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">:</span>
+                <span class="n">update_wrapper</span><span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">callback</span>
+
+    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">&#39;&lt;</span><span class="si">%s</span><span class="s"> </span><span class="si">%r</span><span class="s"> </span><span class="si">%r</span><span class="s">&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">rule</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">callback</span><span class="p">)</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Application Object ###########################################################</span>
+<span class="c">###############################################################################</span>
+
+</div>
+<div class="viewcode-block" id="Bottle"><a class="viewcode-back" href="../api.html#bottle.Bottle">[docs]</a><span class="k">class</span> <span class="nc">Bottle</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Each Bottle object represents a single, distinct web application and</span>
+<span class="sd">        consists of routes, callbacks, plugins, resources and configuration.</span>
+<span class="sd">        Instances are callable WSGI applications.</span>
+
+<span class="sd">        :param catchall: If true (default), handle all exceptions. Turn off to</span>
+<span class="sd">                         let debugging middleware handle exceptions.</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">catchall</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">autojson</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
+        <span class="c">#: If true, most exceptions are caught and returned as :exc:`HTTPError`</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">catchall</span> <span class="o">=</span> <span class="n">catchall</span>
+
+        <span class="c">#: A :class:`ResourceManager` for application files</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">resources</span> <span class="o">=</span> <span class="n">ResourceManager</span><span class="p">()</span>
+
+        <span class="c">#: A :class:`ConfigDict` for app specific configuration.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">config</span> <span class="o">=</span> <span class="n">ConfigDict</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">autojson</span> <span class="o">=</span> <span class="n">autojson</span>
+
+        <span class="bp">self</span><span class="o">.</span><span class="n">routes</span> <span class="o">=</span> <span class="p">[]</span> <span class="c"># List of installed :class:`Route` instances.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">Router</span><span class="p">()</span> <span class="c"># Maps requests to :class:`Route` instances.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">error_handler</span> <span class="o">=</span> <span class="p">{}</span>
+
+        <span class="c"># Core plugins</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">plugins</span> <span class="o">=</span> <span class="p">[]</span> <span class="c"># List of installed plugins.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span> <span class="o">=</span> <span class="n">HooksPlugin</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="p">)</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">autojson</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">JSONPlugin</span><span class="p">())</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">TemplatePlugin</span><span class="p">())</span>
+
+
+<div class="viewcode-block" id="Bottle.mount"><a class="viewcode-back" href="../api.html#bottle.Bottle.mount">[docs]</a>    <span class="k">def</span> <span class="nf">mount</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prefix</span><span class="p">,</span> <span class="n">app</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Mount an application (:class:`Bottle` or plain WSGI) to a specific</span>
+<span class="sd">            URL prefix. Example::</span>
+
+<span class="sd">                root_app.mount(&#39;/admin/&#39;, admin_app)</span>
+
+<span class="sd">            :param prefix: path prefix or `mount-point`. If it ends in a slash,</span>
+<span class="sd">                that slash is mandatory.</span>
+<span class="sd">            :param app: an instance of :class:`Bottle` or a WSGI application.</span>
+
+<span class="sd">            All other parameters are passed to the underlying :meth:`route` call.</span>
+<span class="sd">        &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
+            <span class="n">prefix</span><span class="p">,</span> <span class="n">app</span> <span class="o">=</span> <span class="n">app</span><span class="p">,</span> <span class="n">prefix</span>
+            <span class="n">depr</span><span class="p">(</span><span class="s">&#39;Parameter order of Bottle.mount() changed.&#39;</span><span class="p">)</span> <span class="c"># 0.10</span>
+
+        <span class="n">segments</span> <span class="o">=</span> <span class="p">[</span><span class="n">p</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">prefix</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="n">p</span><span class="p">]</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">segments</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#39;Empty path prefix.&#39;</span><span class="p">)</span>
+        <span class="n">path_depth</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">segments</span><span class="p">)</span>
+
+        <span class="k">def</span> <span class="nf">mountpoint_wrapper</span><span class="p">():</span>
+            <span class="k">try</span><span class="p">:</span>
+                <span class="n">request</span><span class="o">.</span><span class="n">path_shift</span><span class="p">(</span><span class="n">path_depth</span><span class="p">)</span>
+                <span class="n">rs</span> <span class="o">=</span> <span class="n">BaseResponse</span><span class="p">([],</span> <span class="mi">200</span><span class="p">)</span>
+                <span class="k">def</span> <span class="nf">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">header</span><span class="p">):</span>
+                    <span class="n">rs</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">status</span>
+                    <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">header</span><span class="p">:</span> <span class="n">rs</span><span class="o">.</span><span class="n">add_header</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+                    <span class="k">return</span> <span class="n">rs</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">append</span>
+                <span class="n">body</span> <span class="o">=</span> <span class="n">app</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
+                <span class="n">body</span> <span class="o">=</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">(</span><span class="n">rs</span><span class="o">.</span><span class="n">body</span><span class="p">,</span> <span class="n">body</span><span class="p">)</span>
+                <span class="k">return</span> <span class="n">HTTPResponse</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">rs</span><span class="o">.</span><span class="n">status_code</span><span class="p">,</span> <span class="n">rs</span><span class="o">.</span><span class="n">headers</span><span class="p">)</span>
+            <span class="k">finally</span><span class="p">:</span>
+                <span class="n">request</span><span class="o">.</span><span class="n">path_shift</span><span class="p">(</span><span class="o">-</span><span class="n">path_depth</span><span class="p">)</span>
+
+        <span class="n">options</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;skip&#39;</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span>
+        <span class="n">options</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;method&#39;</span><span class="p">,</span> <span class="s">&#39;ANY&#39;</span><span class="p">)</span>
+        <span class="n">options</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;mountpoint&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;prefix&#39;</span><span class="p">:</span> <span class="n">prefix</span><span class="p">,</span> <span class="s">&#39;target&#39;</span><span class="p">:</span> <span class="n">app</span><span class="p">})</span>
+        <span class="n">options</span><span class="p">[</span><span class="s">&#39;callback&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">mountpoint_wrapper</span>
+
+        <span class="bp">self</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s">&#39;/</span><span class="si">%s</span><span class="s">/&lt;:re:.*&gt;&#39;</span> <span class="o">%</span> <span class="s">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">segments</span><span class="p">),</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">prefix</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">):</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="s">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">segments</span><span class="p">),</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.merge"><a class="viewcode-back" href="../api.html#bottle.Bottle.merge">[docs]</a>    <span class="k">def</span> <span class="nf">merge</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">routes</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Merge the routes of another :class:`Bottle` application or a list of</span>
+<span class="sd">            :class:`Route` objects into this application. The routes keep their</span>
+<span class="sd">            &#39;owner&#39;, meaning that the :data:`Route.app` attribute is not</span>
+<span class="sd">            changed. &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">routes</span><span class="p">,</span> <span class="n">Bottle</span><span class="p">):</span>
+            <span class="n">routes</span> <span class="o">=</span> <span class="n">routes</span><span class="o">.</span><span class="n">routes</span>
+        <span class="k">for</span> <span class="n">route</span> <span class="ow">in</span> <span class="n">routes</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">add_route</span><span class="p">(</span><span class="n">route</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.install"><a class="viewcode-back" href="../api.html#bottle.Bottle.install">[docs]</a>    <span class="k">def</span> <span class="nf">install</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">plugin</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add a plugin to the list of plugins and prepare it for being</span>
+<span class="sd">            applied to all routes of this application. A plugin may be a simple</span>
+<span class="sd">            decorator or an object that implements the :class:`Plugin` API.</span>
+<span class="sd">        &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;setup&#39;</span><span class="p">):</span> <span class="n">plugin</span><span class="o">.</span><span class="n">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="nb">callable</span><span class="p">(</span><span class="n">plugin</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;apply&#39;</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&quot;Plugins must be callable or implement .apply()&quot;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">plugins</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">plugin</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
+        <span class="k">return</span> <span class="n">plugin</span>
+</div>
+<div class="viewcode-block" id="Bottle.uninstall"><a class="viewcode-back" href="../api.html#bottle.Bottle.uninstall">[docs]</a>    <span class="k">def</span> <span class="nf">uninstall</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">plugin</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Uninstall plugins. Pass an instance to remove a specific plugin, a type</span>
+<span class="sd">            object to remove all plugins that match that type, a string to remove</span>
+<span class="sd">            all plugins with a matching ``name`` attribute or ``True`` to remove all</span>
+<span class="sd">            plugins. Return the list of removed plugins. &#39;&#39;&#39;</span>
+        <span class="n">removed</span><span class="p">,</span> <span class="n">remove</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">plugin</span>
+        <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">plugin</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="nb">enumerate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">plugins</span><span class="p">))[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
+            <span class="k">if</span> <span class="n">remove</span> <span class="ow">is</span> <span class="bp">True</span> <span class="ow">or</span> <span class="n">remove</span> <span class="ow">is</span> <span class="n">plugin</span> <span class="ow">or</span> <span class="n">remove</span> <span class="ow">is</span> <span class="nb">type</span><span class="p">(</span><span class="n">plugin</span><span class="p">)</span> \
+            <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;name&#39;</span><span class="p">,</span> <span class="bp">True</span><span class="p">)</span> <span class="o">==</span> <span class="n">remove</span><span class="p">:</span>
+                <span class="n">removed</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">plugin</span><span class="p">)</span>
+                <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">plugins</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
+                <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;close&#39;</span><span class="p">):</span> <span class="n">plugin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+        <span class="k">if</span> <span class="n">removed</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
+        <span class="k">return</span> <span class="n">removed</span>
+</div>
+<div class="viewcode-block" id="Bottle.run"><a class="viewcode-back" href="../api.html#bottle.Bottle.run">[docs]</a>    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Calls :func:`run` with the same parameters. &#39;&#39;&#39;</span>
+        <span class="n">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.reset"><a class="viewcode-back" href="../api.html#bottle.Bottle.reset">[docs]</a>    <span class="k">def</span> <span class="nf">reset</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">route</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Reset all routes (force plugins to be re-applied) and clear all</span>
+<span class="sd">            caches. If an ID or route object is given, only that specific route</span>
+<span class="sd">            is affected. &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="n">route</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">routes</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">routes</span>
+        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">route</span><span class="p">,</span> <span class="n">Route</span><span class="p">):</span> <span class="n">routes</span> <span class="o">=</span> <span class="p">[</span><span class="n">route</span><span class="p">]</span>
+        <span class="k">else</span><span class="p">:</span> <span class="n">routes</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">routes</span><span class="p">[</span><span class="n">route</span><span class="p">]]</span>
+        <span class="k">for</span> <span class="n">route</span> <span class="ow">in</span> <span class="n">routes</span><span class="p">:</span> <span class="n">route</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
+        <span class="k">if</span> <span class="n">DEBUG</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">route</span> <span class="ow">in</span> <span class="n">routes</span><span class="p">:</span> <span class="n">route</span><span class="o">.</span><span class="n">prepare</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="o">.</span><span class="n">trigger</span><span class="p">(</span><span class="s">&#39;app_reset&#39;</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.close"><a class="viewcode-back" href="../api.html#bottle.Bottle.close">[docs]</a>    <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Close the application and all installed plugins. &#39;&#39;&#39;</span>
+        <span class="k">for</span> <span class="n">plugin</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">plugins</span><span class="p">:</span>
+            <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">plugin</span><span class="p">,</span> <span class="s">&#39;close&#39;</span><span class="p">):</span> <span class="n">plugin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">stopped</span> <span class="o">=</span> <span class="bp">True</span>
+</div>
+<div class="viewcode-block" id="Bottle.match"><a class="viewcode-back" href="../api.html#bottle.Bottle.match">[docs]</a>    <span class="k">def</span> <span class="nf">match</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Search for a matching route and return a (:class:`Route` , urlargs)</span>
+<span class="sd">            tuple. The second value is a dictionary with parameters extracted</span>
+<span class="sd">            from the URL. Raise :exc:`HTTPError` (404/405) on a non-match.&quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.get_url"><a class="viewcode-back" href="../api.html#bottle.Bottle.get_url">[docs]</a>    <span class="k">def</span> <span class="nf">get_url</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">routename</span><span class="p">,</span> <span class="o">**</span><span class="n">kargs</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Return a string that matches a named route &quot;&quot;&quot;</span>
+        <span class="n">scriptname</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;/&#39;</span>
+        <span class="n">location</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">build</span><span class="p">(</span><span class="n">routename</span><span class="p">,</span> <span class="o">**</span><span class="n">kargs</span><span class="p">)</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">urljoin</span><span class="p">(</span><span class="n">urljoin</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="n">scriptname</span><span class="p">),</span> <span class="n">location</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.add_route"><a class="viewcode-back" href="../api.html#bottle.Bottle.add_route">[docs]</a>    <span class="k">def</span> <span class="nf">add_route</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">route</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add a route object, but do not change the :data:`Route.app`</span>
+<span class="sd">            attribute.&#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">routes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">route</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">route</span><span class="o">.</span><span class="n">rule</span><span class="p">,</span> <span class="n">route</span><span class="o">.</span><span class="n">method</span><span class="p">,</span> <span class="n">route</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">route</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">DEBUG</span><span class="p">:</span> <span class="n">route</span><span class="o">.</span><span class="n">prepare</span><span class="p">()</span>
+</div>
+<div class="viewcode-block" id="Bottle.route"><a class="viewcode-back" href="../api.html#bottle.Bottle.route">[docs]</a>    <span class="k">def</span> <span class="nf">route</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
+              <span class="nb">apply</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">skip</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; A decorator to bind a function to a request URL. Example::</span>
+
+<span class="sd">                @app.route(&#39;/hello/:name&#39;)</span>
+<span class="sd">                def hello(name):</span>
+<span class="sd">                    return &#39;Hello %s&#39; % name</span>
+
+<span class="sd">            The ``:name`` part is a wildcard. See :class:`Router` for syntax</span>
+<span class="sd">            details.</span>
+
+<span class="sd">            :param path: Request path or a list of paths to listen to. If no</span>
+<span class="sd">              path is specified, it is automatically generated from the</span>
+<span class="sd">              signature of the function.</span>
+<span class="sd">            :param method: HTTP method (`GET`, `POST`, `PUT`, ...) or a list of</span>
+<span class="sd">              methods to listen to. (default: `GET`)</span>
+<span class="sd">            :param callback: An optional shortcut to avoid the decorator</span>
+<span class="sd">              syntax. ``route(..., callback=func)`` equals ``route(...)(func)``</span>
+<span class="sd">            :param name: The name for this route. (default: None)</span>
+<span class="sd">            :param apply: A decorator or plugin or a list of plugins. These are</span>
+<span class="sd">              applied to the route callback in addition to installed plugins.</span>
+<span class="sd">            :param skip: A list of plugins, plugin classes or names. Matching</span>
+<span class="sd">              plugins are not installed to this route. ``True`` skips all.</span>
+
+<span class="sd">            Any additional keyword arguments are stored as route-specific</span>
+<span class="sd">            configuration and passed to plugins (see :meth:`Plugin.apply`).</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="k">if</span> <span class="nb">callable</span><span class="p">(</span><span class="n">path</span><span class="p">):</span> <span class="n">path</span><span class="p">,</span> <span class="n">callback</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">path</span>
+        <span class="n">plugins</span> <span class="o">=</span> <span class="n">makelist</span><span class="p">(</span><span class="nb">apply</span><span class="p">)</span>
+        <span class="n">skiplist</span> <span class="o">=</span> <span class="n">makelist</span><span class="p">(</span><span class="n">skip</span><span class="p">)</span>
+        <span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">callback</span><span class="p">):</span>
+            <span class="c"># TODO: Documentation and tests</span>
+            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">callback</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span> <span class="n">callback</span> <span class="o">=</span> <span class="n">load</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span>
+            <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">makelist</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="ow">or</span> <span class="n">yieldroutes</span><span class="p">(</span><span class="n">callback</span><span class="p">):</span>
+                <span class="k">for</span> <span class="n">verb</span> <span class="ow">in</span> <span class="n">makelist</span><span class="p">(</span><span class="n">method</span><span class="p">):</span>
+                    <span class="n">verb</span> <span class="o">=</span> <span class="n">verb</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
+                    <span class="n">route</span> <span class="o">=</span> <span class="n">Route</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">rule</span><span class="p">,</span> <span class="n">verb</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">,</span>
+                                  <span class="n">plugins</span><span class="o">=</span><span class="n">plugins</span><span class="p">,</span> <span class="n">skiplist</span><span class="o">=</span><span class="n">skiplist</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">)</span>
+                    <span class="bp">self</span><span class="o">.</span><span class="n">add_route</span><span class="p">(</span><span class="n">route</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">callback</span>
+        <span class="k">return</span> <span class="n">decorator</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span> <span class="k">if</span> <span class="n">callback</span> <span class="k">else</span> <span class="n">decorator</span>
+</div>
+<div class="viewcode-block" id="Bottle.get"><a class="viewcode-back" href="../api.html#bottle.Bottle.get">[docs]</a>    <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Equals :meth:`route`. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.post"><a class="viewcode-back" href="../api.html#bottle.Bottle.post">[docs]</a>    <span class="k">def</span> <span class="nf">post</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;POST&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Equals :meth:`route` with a ``POST`` method parameter. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.put"><a class="viewcode-back" href="../api.html#bottle.Bottle.put">[docs]</a>    <span class="k">def</span> <span class="nf">put</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;PUT&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Equals :meth:`route` with a ``PUT`` method parameter. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.delete"><a class="viewcode-back" href="../api.html#bottle.Bottle.delete">[docs]</a>    <span class="k">def</span> <span class="nf">delete</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;DELETE&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Equals :meth:`route` with a ``DELETE`` method parameter. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="Bottle.error"><a class="viewcode-back" href="../api.html#bottle.Bottle.error">[docs]</a>    <span class="k">def</span> <span class="nf">error</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">code</span><span class="o">=</span><span class="mi">500</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Decorator: Register an output handler for a HTTP error code&quot;&quot;&quot;</span>
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">handler</span><span class="p">):</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">error_handler</span><span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">code</span><span class="p">)]</span> <span class="o">=</span> <span class="n">handler</span>
+            <span class="k">return</span> <span class="n">handler</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+</div>
+<div class="viewcode-block" id="Bottle.hook"><a class="viewcode-back" href="../api.html#bottle.Bottle.hook">[docs]</a>    <span class="k">def</span> <span class="nf">hook</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Return a decorator that attaches a callback to a hook. Three hooks</span>
+<span class="sd">            are currently implemented:</span>
+
+<span class="sd">            - before_request: Executed once before each request</span>
+<span class="sd">            - after_request: Executed once after each request</span>
+<span class="sd">            - app_reset: Called whenever :meth:`reset` is called.</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">func</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+</div>
+<div class="viewcode-block" id="Bottle.handle"><a class="viewcode-back" href="../api.html#bottle.Bottle.handle">[docs]</a>    <span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; (deprecated) Execute the first matching route callback and return</span>
+<span class="sd">            the result. :exc:`HTTPResponse` exceptions are caught and returned.</span>
+<span class="sd">            If :attr:`Bottle.catchall` is true, other exceptions are caught as</span>
+<span class="sd">            well and returned as :exc:`HTTPError` instances (500).</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&quot;This method will change semantics in 0.10. Try to avoid it.&quot;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">({</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">:</span> <span class="n">path</span><span class="p">,</span> <span class="s">&#39;REQUEST_METHOD&#39;</span><span class="p">:</span> <span class="n">method</span><span class="o">.</span><span class="n">upper</span><span class="p">()})</span>
+</div>
+    <span class="k">def</span> <span class="nf">default_error_handler</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">res</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">tob</span><span class="p">(</span><span class="n">template</span><span class="p">(</span><span class="n">ERROR_PAGE_TEMPLATE</span><span class="p">,</span> <span class="n">e</span><span class="o">=</span><span class="n">res</span><span class="p">))</span>
+
+    <span class="k">def</span> <span class="nf">_handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;bottle.app&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span>
+            <span class="n">request</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
+            <span class="n">response</span><span class="o">.</span><span class="n">bind</span><span class="p">()</span>
+            <span class="n">route</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;route.handle&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">route</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;bottle.route&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">route</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;route.url_args&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">args</span>
+            <span class="k">return</span> <span class="n">route</span><span class="o">.</span><span class="n">call</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
+        <span class="k">except</span> <span class="n">HTTPResponse</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">_e</span><span class="p">()</span>
+        <span class="k">except</span> <span class="n">RouteReset</span><span class="p">:</span>
+            <span class="n">route</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>
+        <span class="k">except</span> <span class="p">(</span><span class="ne">KeyboardInterrupt</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">,</span> <span class="ne">MemoryError</span><span class="p">):</span>
+            <span class="k">raise</span>
+        <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">catchall</span><span class="p">:</span> <span class="k">raise</span>
+            <span class="n">stacktrace</span> <span class="o">=</span> <span class="n">format_exc</span><span class="p">()</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.errors&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">stacktrace</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s">&quot;Internal Server Error&quot;</span><span class="p">,</span> <span class="n">_e</span><span class="p">(),</span> <span class="n">stacktrace</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">_cast</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">out</span><span class="p">,</span> <span class="n">peek</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Try to convert the parameter into something WSGI compatible and set</span>
+<span class="sd">        correct HTTP headers when possible.</span>
+<span class="sd">        Support: False, str, unicode, dict, HTTPResponse, HTTPError, file-like,</span>
+<span class="sd">        iterable of strings and iterable of unicodes</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+
+        <span class="c"># Empty output is done here</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">out</span><span class="p">:</span>
+            <span class="k">if</span> <span class="s">&#39;Content-Length&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">response</span><span class="p">:</span>
+                <span class="n">response</span><span class="p">[</span><span class="s">&#39;Content-Length&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
+            <span class="k">return</span> <span class="p">[]</span>
+        <span class="c"># Join lists of byte or unicode strings. Mixed lists are NOT supported</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">))</span>\
+        <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)):</span>
+            <span class="n">out</span> <span class="o">=</span> <span class="n">out</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">:</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">out</span><span class="p">)</span> <span class="c"># b&#39;abc&#39;[0:0] -&gt; b&#39;&#39;</span>
+        <span class="c"># Encode unicode strings</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">):</span>
+            <span class="n">out</span> <span class="o">=</span> <span class="n">out</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">charset</span><span class="p">)</span>
+        <span class="c"># Byte Strings are just returned</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
+            <span class="k">if</span> <span class="s">&#39;Content-Length&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">response</span><span class="p">:</span>
+                <span class="n">response</span><span class="p">[</span><span class="s">&#39;Content-Length&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
+            <span class="k">return</span> <span class="p">[</span><span class="n">out</span><span class="p">]</span>
+        <span class="c"># HTTPError or HTTPException (recursive, because they may wrap anything)</span>
+        <span class="c"># TODO: Handle these explicitly in handle() or make them iterable.</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="n">HTTPError</span><span class="p">):</span>
+            <span class="n">out</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
+            <span class="n">out</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">error_handler</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">out</span><span class="o">.</span><span class="n">status_code</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_error_handler</span><span class="p">)(</span><span class="n">out</span><span class="p">)</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cast</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="n">HTTPResponse</span><span class="p">):</span>
+            <span class="n">out</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cast</span><span class="p">(</span><span class="n">out</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>
+
+        <span class="c"># File-like objects.</span>
+        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="s">&#39;read&#39;</span><span class="p">):</span>
+            <span class="k">if</span> <span class="s">&#39;wsgi.file_wrapper&#39;</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">:</span>
+                <span class="k">return</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.file_wrapper&#39;</span><span class="p">](</span><span class="n">out</span><span class="p">)</span>
+            <span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="s">&#39;close&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="s">&#39;__iter__&#39;</span><span class="p">):</span>
+                <span class="k">return</span> <span class="n">WSGIFileWrapper</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
+
+        <span class="c"># Handle Iterables. We peek into them to detect their inner type.</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">out</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
+            <span class="n">first</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
+            <span class="k">while</span> <span class="ow">not</span> <span class="n">first</span><span class="p">:</span>
+                <span class="n">first</span> <span class="o">=</span> <span class="nb">next</span><span class="p">(</span><span class="n">out</span><span class="p">)</span>
+        <span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cast</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">)</span>
+        <span class="k">except</span> <span class="n">HTTPResponse</span><span class="p">:</span>
+            <span class="n">first</span> <span class="o">=</span> <span class="n">_e</span><span class="p">()</span>
+        <span class="k">except</span> <span class="p">(</span><span class="ne">KeyboardInterrupt</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">,</span> <span class="ne">MemoryError</span><span class="p">):</span>
+            <span class="k">raise</span>
+        <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">catchall</span><span class="p">:</span> <span class="k">raise</span>
+            <span class="n">first</span> <span class="o">=</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s">&#39;Unhandled exception&#39;</span><span class="p">,</span> <span class="n">_e</span><span class="p">(),</span> <span class="n">format_exc</span><span class="p">())</span>
+
+        <span class="c"># These are the inner types allowed in iterator or generator objects.</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">HTTPResponse</span><span class="p">):</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cast</span><span class="p">(</span><span class="n">first</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
+            <span class="k">return</span> <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">([</span><span class="n">first</span><span class="p">],</span> <span class="n">out</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">):</span>
+            <span class="k">return</span> <span class="n">imap</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">charset</span><span class="p">),</span>
+                                  <span class="n">itertools</span><span class="o">.</span><span class="n">chain</span><span class="p">([</span><span class="n">first</span><span class="p">],</span> <span class="n">out</span><span class="p">))</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cast</span><span class="p">(</span><span class="n">HTTPError</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s">&#39;Unsupported response type: </span><span class="si">%s</span><span class="s">&#39;</span>\
+                                         <span class="o">%</span> <span class="nb">type</span><span class="p">(</span><span class="n">first</span><span class="p">)))</span>
+
+<div class="viewcode-block" id="Bottle.wsgi"><a class="viewcode-back" href="../api.html#bottle.Bottle.wsgi">[docs]</a>    <span class="k">def</span> <span class="nf">wsgi</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; The bottle WSGI-interface. &quot;&quot;&quot;</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">out</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cast</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">(</span><span class="n">environ</span><span class="p">))</span>
+            <span class="c"># rfc2616 section 4.3</span>
+            <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">_status_code</span> <span class="ow">in</span> <span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">101</span><span class="p">,</span> <span class="mi">204</span><span class="p">,</span> <span class="mi">304</span><span class="p">)</span>\
+            <span class="ow">or</span> <span class="n">environ</span><span class="p">[</span><span class="s">&#39;REQUEST_METHOD&#39;</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;HEAD&#39;</span><span class="p">:</span>
+                <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="s">&#39;close&#39;</span><span class="p">):</span> <span class="n">out</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+                <span class="n">out</span> <span class="o">=</span> <span class="p">[]</span>
+            <span class="n">start_response</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">_status_line</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">headerlist</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">out</span>
+        <span class="k">except</span> <span class="p">(</span><span class="ne">KeyboardInterrupt</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">,</span> <span class="ne">MemoryError</span><span class="p">):</span>
+            <span class="k">raise</span>
+        <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">catchall</span><span class="p">:</span> <span class="k">raise</span>
+            <span class="n">err</span> <span class="o">=</span> <span class="s">&#39;&lt;h1&gt;Critical error while processing request: </span><span class="si">%s</span><span class="s">&lt;/h1&gt;&#39;</span> \
+                  <span class="o">%</span> <span class="n">html_escape</span><span class="p">(</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">,</span> <span class="s">&#39;/&#39;</span><span class="p">))</span>
+            <span class="k">if</span> <span class="n">DEBUG</span><span class="p">:</span>
+                <span class="n">err</span> <span class="o">+=</span> <span class="s">&#39;&lt;h2&gt;Error:&lt;/h2&gt;</span><span class="se">\n</span><span class="s">&lt;pre&gt;</span><span class="se">\n</span><span class="si">%s</span><span class="se">\n</span><span class="s">&lt;/pre&gt;</span><span class="se">\n</span><span class="s">&#39;</span> \
+                       <span class="s">&#39;&lt;h2&gt;Traceback:&lt;/h2&gt;</span><span class="se">\n</span><span class="s">&lt;pre&gt;</span><span class="se">\n</span><span class="si">%s</span><span class="se">\n</span><span class="s">&lt;/pre&gt;</span><span class="se">\n</span><span class="s">&#39;</span> \
+                       <span class="o">%</span> <span class="p">(</span><span class="n">html_escape</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">_e</span><span class="p">())),</span> <span class="n">html_escape</span><span class="p">(</span><span class="n">format_exc</span><span class="p">()))</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.errors&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
+            <span class="n">headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;Content-Type&#39;</span><span class="p">,</span> <span class="s">&#39;text/html; charset=UTF-8&#39;</span><span class="p">)]</span>
+            <span class="n">start_response</span><span class="p">(</span><span class="s">&#39;500 INTERNAL SERVER ERROR&#39;</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
+            <span class="k">return</span> <span class="p">[</span><span class="n">tob</span><span class="p">(</span><span class="n">err</span><span class="p">)]</span>
+</div>
+    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Each instance of :class:&#39;Bottle&#39; is a WSGI application. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">wsgi</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># HTTP and WSGI Tools ##########################################################</span>
+<span class="c">###############################################################################</span>
+
+</div>
+<div class="viewcode-block" id="BaseRequest"><a class="viewcode-back" href="../api.html#bottle.BaseRequest">[docs]</a><span class="k">class</span> <span class="nc">BaseRequest</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; A wrapper for WSGI environment dictionaries that adds a lot of</span>
+<span class="sd">        convenient access methods and properties. Most of them are read-only.</span>
+
+<span class="sd">        Adding new attributes to a request actually adds them to the environ</span>
+<span class="sd">        dictionary (as &#39;bottle.request.ext.&lt;name&gt;&#39;). This is the recommended</span>
+<span class="sd">        way to store and access request-specific data.</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+
+    <span class="n">__slots__</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">)</span>
+
+    <span class="c">#: Maximum size of memory buffer for :attr:`body` in bytes.</span>
+    <span class="n">MEMFILE_MAX</span> <span class="o">=</span> <span class="mi">102400</span>
+    <span class="c">#: Maximum number pr GET or POST parameters per request</span>
+    <span class="n">MAX_PARAMS</span>  <span class="o">=</span> <span class="mi">100</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Wrap a WSGI environ dictionary. &quot;&quot;&quot;</span>
+        <span class="c">#: The wrapped WSGI environ dictionary. This is the only real attribute.</span>
+        <span class="c">#: All other attributes actually are read-only properties.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">environ</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">if</span> <span class="n">environ</span> <span class="ow">is</span> <span class="bp">None</span> <span class="k">else</span> <span class="n">environ</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;bottle.request&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span>
+
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.app&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.app"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.app">[docs]</a>    <span class="k">def</span> <span class="nf">app</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Bottle application handling this request. &#39;&#39;&#39;</span>
+        <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&#39;This request is not connected to an application.&#39;</span><span class="p">)</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.path"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.path">[docs]</a>    <span class="k">def</span> <span class="nf">path</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The value of ``PATH_INFO`` with exactly one prefixed slash (to fix</span>
+<span class="sd">            broken clients and avoid the &quot;empty path&quot; edge case). &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.method"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.method">[docs]</a>    <span class="k">def</span> <span class="nf">method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The ``REQUEST_METHOD`` value as an uppercase string. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;REQUEST_METHOD&#39;</span><span class="p">,</span> <span class="s">&#39;GET&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.headers&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.headers"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.headers">[docs]</a>    <span class="k">def</span> <span class="nf">headers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; A :class:`WSGIHeaderDict` that provides case-insensitive access to</span>
+<span class="sd">            HTTP request headers. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="n">WSGIHeaderDict</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="BaseRequest.get_header"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.get_header">[docs]</a>    <span class="k">def</span> <span class="nf">get_header</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Return the value of a request header, or a given default value. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.cookies&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.cookies"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.cookies">[docs]</a>    <span class="k">def</span> <span class="nf">cookies</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Cookies parsed into a :class:`FormsDict`. Signed cookies are NOT</span>
+<span class="sd">            decoded. Use :meth:`get_cookie` if you expect signed cookies. &quot;&quot;&quot;</span>
+        <span class="n">cookies</span> <span class="o">=</span> <span class="n">SimpleCookie</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_COOKIE&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">))</span>
+        <span class="n">cookies</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">cookies</span><span class="o">.</span><span class="n">values</span><span class="p">())[:</span><span class="bp">self</span><span class="o">.</span><span class="n">MAX_PARAMS</span><span class="p">]</span>
+        <span class="k">return</span> <span class="n">FormsDict</span><span class="p">((</span><span class="n">c</span><span class="o">.</span><span class="n">key</span><span class="p">,</span> <span class="n">c</span><span class="o">.</span><span class="n">value</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">cookies</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="BaseRequest.get_cookie"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.get_cookie">[docs]</a>    <span class="k">def</span> <span class="nf">get_cookie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">secret</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Return the content of a cookie. To read a `Signed Cookie`, the</span>
+<span class="sd">            `secret` must match the one used to create the cookie (see</span>
+<span class="sd">            :meth:`BaseResponse.set_cookie`). If anything goes wrong (missing</span>
+<span class="sd">            cookie or wrong signature), return a default value. &quot;&quot;&quot;</span>
+        <span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">secret</span> <span class="ow">and</span> <span class="n">value</span><span class="p">:</span>
+            <span class="n">dec</span> <span class="o">=</span> <span class="n">cookie_decode</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">secret</span><span class="p">)</span> <span class="c"># (key, value) tuple or None</span>
+            <span class="k">return</span> <span class="n">dec</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">dec</span> <span class="ow">and</span> <span class="n">dec</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">key</span> <span class="k">else</span> <span class="n">default</span>
+        <span class="k">return</span> <span class="n">value</span> <span class="ow">or</span> <span class="n">default</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.query&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.query"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.query">[docs]</a>    <span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The :attr:`query_string` parsed into a :class:`FormsDict`. These</span>
+<span class="sd">            values are sometimes called &quot;URL arguments&quot; or &quot;GET parameters&quot;, but</span>
+<span class="sd">            not to be confused with &quot;URL wildcards&quot; as they are provided by the</span>
+<span class="sd">            :class:`Router`. &#39;&#39;&#39;</span>
+        <span class="n">get</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;bottle.get&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">FormsDict</span><span class="p">()</span>
+        <span class="n">pairs</span> <span class="o">=</span> <span class="n">_parse_qsl</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;QUERY_STRING&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">))</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">pairs</span><span class="p">[:</span><span class="bp">self</span><span class="o">.</span><span class="n">MAX_PARAMS</span><span class="p">]:</span>
+            <span class="n">get</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+        <span class="k">return</span> <span class="n">get</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.forms&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.forms"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.forms">[docs]</a>    <span class="k">def</span> <span class="nf">forms</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Form values parsed from an `url-encoded` or `multipart/form-data`</span>
+<span class="sd">            encoded POST or PUT request body. The result is retuned as a</span>
+<span class="sd">            :class:`FormsDict`. All keys and values are strings. File uploads</span>
+<span class="sd">            are stored separately in :attr:`files`. &quot;&quot;&quot;</span>
+        <span class="n">forms</span> <span class="o">=</span> <span class="n">FormsDict</span><span class="p">()</span>
+        <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">POST</span><span class="o">.</span><span class="n">allitems</span><span class="p">():</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="s">&#39;filename&#39;</span><span class="p">):</span>
+                <span class="n">forms</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">item</span>
+        <span class="k">return</span> <span class="n">forms</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.params&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.params"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.params">[docs]</a>    <span class="k">def</span> <span class="nf">params</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; A :class:`FormsDict` with the combined values of :attr:`query` and</span>
+<span class="sd">            :attr:`forms`. File uploads are stored in :attr:`files`. &quot;&quot;&quot;</span>
+        <span class="n">params</span> <span class="o">=</span> <span class="n">FormsDict</span><span class="p">()</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">allitems</span><span class="p">():</span>
+            <span class="n">params</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">allitems</span><span class="p">():</span>
+            <span class="n">params</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+        <span class="k">return</span> <span class="n">params</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.files&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.files"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.files">[docs]</a>    <span class="k">def</span> <span class="nf">files</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; File uploads parsed from an `url-encoded` or `multipart/form-data`</span>
+<span class="sd">            encoded POST or PUT request body. The values are instances of</span>
+<span class="sd">            :class:`cgi.FieldStorage`. The most important attributes are:</span>
+
+<span class="sd">            filename</span>
+<span class="sd">                The filename, if specified; otherwise None; this is the client</span>
+<span class="sd">                side filename, *not* the file name on which it is stored (that&#39;s</span>
+<span class="sd">                a temporary file you don&#39;t deal with)</span>
+<span class="sd">            file</span>
+<span class="sd">                The file(-like) object from which you can read the data.</span>
+<span class="sd">            value</span>
+<span class="sd">                The value as a *string*; for file uploads, this transparently</span>
+<span class="sd">                reads the file every time you request the value. Do not do this</span>
+<span class="sd">                on big files.</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">files</span> <span class="o">=</span> <span class="n">FormsDict</span><span class="p">()</span>
+        <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">item</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">POST</span><span class="o">.</span><span class="n">allitems</span><span class="p">():</span>
+            <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="s">&#39;filename&#39;</span><span class="p">):</span>
+                <span class="n">files</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">item</span>
+        <span class="k">return</span> <span class="n">files</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.json&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.json"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.json">[docs]</a>    <span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; If the ``Content-Type`` header is ``application/json``, this</span>
+<span class="sd">            property holds the parsed content of the request body. Only requests</span>
+<span class="sd">            smaller than :attr:`MEMFILE_MAX` are processed to avoid memory</span>
+<span class="sd">            exhaustion. &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="s">&#39;application/json&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;CONTENT_TYPE&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span> \
+        <span class="ow">and</span> <span class="mi">0</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">content_length</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">MEMFILE_MAX</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">json_loads</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">MEMFILE_MAX</span><span class="p">))</span>
+        <span class="k">return</span> <span class="bp">None</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.body&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">_body</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">maxread</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">content_length</span><span class="p">)</span>
+        <span class="n">stream</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.input&#39;</span><span class="p">]</span>
+        <span class="n">body</span> <span class="o">=</span> <span class="n">BytesIO</span><span class="p">()</span> <span class="k">if</span> <span class="n">maxread</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">MEMFILE_MAX</span> <span class="k">else</span> <span class="n">TemporaryFile</span><span class="p">(</span><span class="n">mode</span><span class="o">=</span><span class="s">&#39;w+b&#39;</span><span class="p">)</span>
+        <span class="k">while</span> <span class="n">maxread</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
+            <span class="n">part</span> <span class="o">=</span> <span class="n">stream</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">maxread</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">MEMFILE_MAX</span><span class="p">))</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">part</span><span class="p">:</span> <span class="k">break</span>
+            <span class="n">body</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">part</span><span class="p">)</span>
+            <span class="n">maxread</span> <span class="o">-=</span> <span class="nb">len</span><span class="p">(</span><span class="n">part</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.input&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">body</span>
+        <span class="n">body</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">body</span>
+
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.body"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.body">[docs]</a>    <span class="k">def</span> <span class="nf">body</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; The HTTP request body as a seek-able file-like object. Depending on</span>
+<span class="sd">            :attr:`MEMFILE_MAX`, this is either a temporary file or a</span>
+<span class="sd">            :class:`io.BytesIO` instance. Accessing this property for the first</span>
+<span class="sd">            time reads and replaces the ``wsgi.input`` environ variable.</span>
+<span class="sd">            Subsequent accesses just do a `seek(0)` on the file object. &quot;&quot;&quot;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_body</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_body</span>
+
+    <span class="c">#: An alias for :attr:`query`.</span></div>
+    <span class="n">GET</span> <span class="o">=</span> <span class="n">query</span>
+
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.post&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.POST"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.POST">[docs]</a>    <span class="k">def</span> <span class="nf">POST</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; The values of :attr:`forms` and :attr:`files` combined into a single</span>
+<span class="sd">            :class:`FormsDict`. Values are either strings (form values) or</span>
+<span class="sd">            instances of :class:`cgi.FieldStorage` (file uploads).</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="n">post</span> <span class="o">=</span> <span class="n">FormsDict</span><span class="p">()</span>
+        <span class="c"># We default to application/x-www-form-urlencoded for everything that</span>
+        <span class="c"># is not multipart and take the fast path (also: 3.1 workaround)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">content_type</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;multipart/&#39;</span><span class="p">):</span>
+            <span class="n">maxlen</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">min</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">content_length</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">MEMFILE_MAX</span><span class="p">))</span>
+            <span class="n">pairs</span> <span class="o">=</span> <span class="n">_parse_qsl</span><span class="p">(</span><span class="n">tonat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">maxlen</span><span class="p">),</span> <span class="s">&#39;latin1&#39;</span><span class="p">))</span>
+            <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">pairs</span><span class="p">[:</span><span class="bp">self</span><span class="o">.</span><span class="n">MAX_PARAMS</span><span class="p">]:</span>
+                <span class="n">post</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+            <span class="k">return</span> <span class="n">post</span>
+
+        <span class="n">safe_env</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;QUERY_STRING&#39;</span><span class="p">:</span><span class="s">&#39;&#39;</span><span class="p">}</span> <span class="c"># Build a safe environment for cgi</span>
+        <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;REQUEST_METHOD&#39;</span><span class="p">,</span> <span class="s">&#39;CONTENT_TYPE&#39;</span><span class="p">,</span> <span class="s">&#39;CONTENT_LENGTH&#39;</span><span class="p">):</span>
+            <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">:</span> <span class="n">safe_env</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
+        <span class="n">args</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">fp</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="p">,</span> <span class="n">environ</span><span class="o">=</span><span class="n">safe_env</span><span class="p">,</span> <span class="n">keep_blank_values</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">py31</span><span class="p">:</span>
+            <span class="n">args</span><span class="p">[</span><span class="s">&#39;fp&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">NCTextIOWrapper</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="s">&#39;fp&#39;</span><span class="p">],</span> <span class="n">encoding</span><span class="o">=</span><span class="s">&#39;ISO-8859-1&#39;</span><span class="p">,</span>
+                                         <span class="n">newline</span><span class="o">=</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="n">py3k</span><span class="p">:</span>
+            <span class="n">args</span><span class="p">[</span><span class="s">&#39;encoding&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;ISO-8859-1&#39;</span>
+        <span class="n">data</span> <span class="o">=</span> <span class="n">FieldStorage</span><span class="p">(</span><span class="o">**</span><span class="n">args</span><span class="p">)</span>
+        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">list</span> <span class="ow">or</span> <span class="p">[])[:</span><span class="bp">self</span><span class="o">.</span><span class="n">MAX_PARAMS</span><span class="p">]:</span>
+            <span class="n">post</span><span class="p">[</span><span class="n">item</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">item</span> <span class="k">if</span> <span class="n">item</span><span class="o">.</span><span class="n">filename</span> <span class="k">else</span> <span class="n">item</span><span class="o">.</span><span class="n">value</span>
+        <span class="k">return</span> <span class="n">post</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.COOKIES"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.COOKIES">[docs]</a>    <span class="k">def</span> <span class="nf">COOKIES</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Alias for :attr:`cookies` (deprecated). &#39;&#39;&#39;</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&#39;BaseRequest.COOKIES was renamed to BaseRequest.cookies (lowercase).&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">cookies</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.url"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.url">[docs]</a>    <span class="k">def</span> <span class="nf">url</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; The full request URI including hostname and scheme. If your app</span>
+<span class="sd">            lives behind a reverse proxy or load balancer and you get confusing</span>
+<span class="sd">            results, make sure that the ``X-Forwarded-Host`` header is set</span>
+<span class="sd">            correctly. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">urlparts</span><span class="o">.</span><span class="n">geturl</span><span class="p">()</span>
+</div>
+    <span class="nd">@DictProperty</span><span class="p">(</span><span class="s">&#39;environ&#39;</span><span class="p">,</span> <span class="s">&#39;bottle.request.urlparts&#39;</span><span class="p">,</span> <span class="n">read_only</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<div class="viewcode-block" id="BaseRequest.urlparts"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.urlparts">[docs]</a>    <span class="k">def</span> <span class="nf">urlparts</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The :attr:`url` string as an :class:`urlparse.SplitResult` tuple.</span>
+<span class="sd">            The tuple contains (scheme, host, path, query_string and fragment),</span>
+<span class="sd">            but the fragment is always empty because it is not visible to the</span>
+<span class="sd">            server. &#39;&#39;&#39;</span>
+        <span class="n">env</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span>
+        <span class="n">http</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_X_FORWARDED_PROTO&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;wsgi.url_scheme&#39;</span><span class="p">,</span> <span class="s">&#39;http&#39;</span><span class="p">)</span>
+        <span class="n">host</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_X_FORWARDED_HOST&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_HOST&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">host</span><span class="p">:</span>
+            <span class="c"># HTTP 1.1 requires a Host-header. This is for HTTP/1.0 clients.</span>
+            <span class="n">host</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SERVER_NAME&#39;</span><span class="p">,</span> <span class="s">&#39;127.0.0.1&#39;</span><span class="p">)</span>
+            <span class="n">port</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SERVER_PORT&#39;</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">port</span> <span class="ow">and</span> <span class="n">port</span> <span class="o">!=</span> <span class="p">(</span><span class="s">&#39;80&#39;</span> <span class="k">if</span> <span class="n">http</span> <span class="o">==</span> <span class="s">&#39;http&#39;</span> <span class="k">else</span> <span class="s">&#39;443&#39;</span><span class="p">):</span>
+                <span class="n">host</span> <span class="o">+=</span> <span class="s">&#39;:&#39;</span> <span class="o">+</span> <span class="n">port</span>
+        <span class="n">path</span> <span class="o">=</span> <span class="n">urlquote</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">fullpath</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">UrlSplitResult</span><span class="p">(</span><span class="n">http</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;QUERY_STRING&#39;</span><span class="p">),</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.fullpath"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.fullpath">[docs]</a>    <span class="k">def</span> <span class="nf">fullpath</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Request path including :attr:`script_name` (if present). &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="n">urljoin</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">script_name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">))</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.query_string"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.query_string">[docs]</a>    <span class="k">def</span> <span class="nf">query_string</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; The raw :attr:`query` part of the URL (everything in between ``?``</span>
+<span class="sd">            and ``#``) as a string. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;QUERY_STRING&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.script_name"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.script_name">[docs]</a>    <span class="k">def</span> <span class="nf">script_name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The initial portion of the URL&#39;s `path` that was removed by a higher</span>
+<span class="sd">            level (server or routing middleware) before the application was</span>
+<span class="sd">            called. This script path is returned with leading and tailing</span>
+<span class="sd">            slashes. &#39;&#39;&#39;</span>
+        <span class="n">script_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="n">script_name</span> <span class="o">+</span> <span class="s">&#39;/&#39;</span> <span class="k">if</span> <span class="n">script_name</span> <span class="k">else</span> <span class="s">&#39;/&#39;</span>
+</div>
+<div class="viewcode-block" id="BaseRequest.path_shift"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.path_shift">[docs]</a>    <span class="k">def</span> <span class="nf">path_shift</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">shift</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Shift path segments from :attr:`path` to :attr:`script_name` and</span>
+<span class="sd">            vice versa.</span>
+
+<span class="sd">           :param shift: The number of path segments to shift. May be negative</span>
+<span class="sd">                         to change the shift direction. (default: 1)</span>
+<span class="sd">        &#39;&#39;&#39;</span>
+        <span class="n">script</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">,</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="p">[</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">],</span> <span class="bp">self</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">path_shift</span><span class="p">(</span><span class="n">script</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">,</span> <span class="n">shift</span><span class="p">)</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.content_length"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.content_length">[docs]</a>    <span class="k">def</span> <span class="nf">content_length</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The request body length as an integer. The client is responsible to</span>
+<span class="sd">            set this header. Otherwise, the real length of the body is unknown</span>
+<span class="sd">            and -1 is returned. In this case, :attr:`body` will be empty. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;CONTENT_LENGTH&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.content_type"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.content_type">[docs]</a>    <span class="k">def</span> <span class="nf">content_type</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The Content-Type header as a lowercase-string (default: empty). &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;CONTENT_TYPE&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.is_xhr"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.is_xhr">[docs]</a>    <span class="k">def</span> <span class="nf">is_xhr</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; True if the request was triggered by a XMLHttpRequest. This only</span>
+<span class="sd">            works with JavaScript libraries that support the `X-Requested-With`</span>
+<span class="sd">            header (most of the popular libraries do). &#39;&#39;&#39;</span>
+        <span class="n">requested_with</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_X_REQUESTED_WITH&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">requested_with</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s">&#39;xmlhttprequest&#39;</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.is_ajax"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.is_ajax">[docs]</a>    <span class="k">def</span> <span class="nf">is_ajax</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Alias for :attr:`is_xhr`. &quot;Ajax&quot; is not the right term. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_xhr</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.auth"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.auth">[docs]</a>    <span class="k">def</span> <span class="nf">auth</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; HTTP authentication data as a (user, password) tuple. This</span>
+<span class="sd">            implementation currently supports basic (not digest) authentication</span>
+<span class="sd">            only. If the authentication happened at a higher level (e.g. in the</span>
+<span class="sd">            front web-server or a middleware), the password field is None, but</span>
+<span class="sd">            the user field is looked up from the ``REMOTE_USER`` environ</span>
+<span class="sd">            variable. On any errors, None is returned. &quot;&quot;&quot;</span>
+        <span class="n">basic</span> <span class="o">=</span> <span class="n">parse_auth</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_AUTHORIZATION&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">))</span>
+        <span class="k">if</span> <span class="n">basic</span><span class="p">:</span> <span class="k">return</span> <span class="n">basic</span>
+        <span class="n">ruser</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;REMOTE_USER&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">ruser</span><span class="p">:</span> <span class="k">return</span> <span class="p">(</span><span class="n">ruser</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">None</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.remote_route"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.remote_route">[docs]</a>    <span class="k">def</span> <span class="nf">remote_route</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; A list of all IPs that were involved in this request, starting with</span>
+<span class="sd">            the client IP and followed by zero or more proxies. This does only</span>
+<span class="sd">            work if all proxies support the ```X-Forwarded-For`` header. Note</span>
+<span class="sd">            that this information can be forged by malicious clients. &quot;&quot;&quot;</span>
+        <span class="n">proxy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_X_FORWARDED_FOR&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">proxy</span><span class="p">:</span> <span class="k">return</span> <span class="p">[</span><span class="n">ip</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">ip</span> <span class="ow">in</span> <span class="n">proxy</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;,&#39;</span><span class="p">)]</span>
+        <span class="n">remote</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;REMOTE_ADDR&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="p">[</span><span class="n">remote</span><span class="p">]</span> <span class="k">if</span> <span class="n">remote</span> <span class="k">else</span> <span class="p">[]</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseRequest.remote_addr"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.remote_addr">[docs]</a>    <span class="k">def</span> <span class="nf">remote_addr</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; The client IP as a string. Note that this information can be forged</span>
+<span class="sd">            by malicious clients. &quot;&quot;&quot;</span>
+        <span class="n">route</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">remote_route</span>
+        <span class="k">return</span> <span class="n">route</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">route</span> <span class="k">else</span> <span class="bp">None</span>
+</div>
+<div class="viewcode-block" id="BaseRequest.copy"><a class="viewcode-back" href="../api.html#bottle.BaseRequest.copy">[docs]</a>    <span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Return a new :class:`Request` with a shallow :attr:`environ` copy. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="n">Request</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">copy</span><span class="p">())</span>
+</div>
+    <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="bp">self</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;&quot;</span><span class="p">;</span> <span class="k">del</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="n">key</span><span class="p">])</span>
+    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">keys</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
+    <span class="k">def</span> <span class="nf">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Change an environ value and clear all caches that depend on it. &quot;&quot;&quot;</span>
+
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;bottle.request.readonly&#39;</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="s">&#39;The environ dictionary is read-only.&#39;</span><span class="p">)</span>
+
+        <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+        <span class="n">todelete</span> <span class="o">=</span> <span class="p">()</span>
+
+        <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;wsgi.input&#39;</span><span class="p">:</span>
+            <span class="n">todelete</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;body&#39;</span><span class="p">,</span> <span class="s">&#39;forms&#39;</span><span class="p">,</span> <span class="s">&#39;files&#39;</span><span class="p">,</span> <span class="s">&#39;params&#39;</span><span class="p">,</span> <span class="s">&#39;post&#39;</span><span class="p">,</span> <span class="s">&#39;json&#39;</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;QUERY_STRING&#39;</span><span class="p">:</span>
+            <span class="n">todelete</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;query&#39;</span><span class="p">,</span> <span class="s">&#39;params&#39;</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;HTTP_&#39;</span><span class="p">):</span>
+            <span class="n">todelete</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;headers&#39;</span><span class="p">,</span> <span class="s">&#39;cookies&#39;</span><span class="p">)</span>
+
+        <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">todelete</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;bottle.request.&#39;</span><span class="o">+</span><span class="n">key</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">&#39;&lt;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Search in self.environ for additional user defined attributes. &#39;&#39;&#39;</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">var</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;bottle.request.ext.</span><span class="si">%s</span><span class="s">&#39;</span><span class="o">%</span><span class="n">name</span><span class="p">]</span>
+            <span class="k">return</span> <span class="n">var</span><span class="o">.</span><span class="n">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">var</span><span class="p">,</span> <span class="s">&#39;__get__&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="n">var</span>
+        <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s">&#39;Attribute </span><span class="si">%r</span><span class="s"> not defined.&#39;</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__setattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">name</span> <span class="o">==</span> <span class="s">&#39;environ&#39;</span><span class="p">:</span> <span class="k">return</span> <span class="nb">object</span><span class="o">.</span><span class="n">__setattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;bottle.request.ext.</span><span class="si">%s</span><span class="s">&#39;</span><span class="o">%</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+
+
+
+</div>
+<span class="k">def</span> <span class="nf">_hkey</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="n">title</span><span class="p">()</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;_&#39;</span><span class="p">,</span><span class="s">&#39;-&#39;</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">HeaderProperty</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">reader</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">writer</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s">&#39;&#39;</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">reader</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">writer</span> <span class="o">=</span> <span class="n">reader</span><span class="p">,</span> <span class="n">writer</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">__doc__</span> <span class="o">=</span> <span class="s">&#39;Current value of the </span><span class="si">%r</span><span class="s"> header.&#39;</span> <span class="o">%</span> <span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">__get__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">cls</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span>
+        <span class="n">value</span> <span class="o">=</span> <span class="n">obj</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">default</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">reader</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">reader</span> <span class="k">else</span> <span class="n">value</span>
+
+    <span class="k">def</span> <span class="nf">__set__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="n">obj</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">writer</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__delete__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
+        <span class="k">del</span> <span class="n">obj</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">]</span>
+
+
+<div class="viewcode-block" id="BaseResponse"><a class="viewcode-back" href="../api.html#bottle.BaseResponse">[docs]</a><span class="k">class</span> <span class="nc">BaseResponse</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Storage class for a response body as well as headers and cookies.</span>
+
+<span class="sd">        This class does support dict-like case-insensitive item-access to</span>
+<span class="sd">        headers, but is NOT a dict. Most notably, iterating over a response</span>
+<span class="sd">        yields parts of the body and not the headers.</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+
+    <span class="n">default_status</span> <span class="o">=</span> <span class="mi">200</span>
+    <span class="n">default_content_type</span> <span class="o">=</span> <span class="s">&#39;text/html; charset=UTF-8&#39;</span>
+
+    <span class="c"># Header blacklist for specific response codes</span>
+    <span class="c"># (rfc2616 section 10.2.3 and 10.3.5)</span>
+    <span class="n">bad_headers</span> <span class="o">=</span> <span class="p">{</span>
+        <span class="mi">204</span><span class="p">:</span> <span class="nb">set</span><span class="p">((</span><span class="s">&#39;Content-Type&#39;</span><span class="p">,)),</span>
+        <span class="mi">304</span><span class="p">:</span> <span class="nb">set</span><span class="p">((</span><span class="s">&#39;Allow&#39;</span><span class="p">,</span> <span class="s">&#39;Content-Encoding&#39;</span><span class="p">,</span> <span class="s">&#39;Content-Language&#39;</span><span class="p">,</span>
+                  <span class="s">&#39;Content-Length&#39;</span><span class="p">,</span> <span class="s">&#39;Content-Range&#39;</span><span class="p">,</span> <span class="s">&#39;Content-Type&#39;</span><span class="p">,</span>
+                  <span class="s">&#39;Content-Md5&#39;</span><span class="p">,</span> <span class="s">&#39;Last-Modified&#39;</span><span class="p">))}</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span> <span class="o">=</span> <span class="bp">None</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;Content-Type&#39;</span><span class="p">:</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">default_content_type</span><span class="p">]}</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">body</span> <span class="o">=</span> <span class="n">body</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">status</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">default_status</span>
+        <span class="k">if</span> <span class="n">headers</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">headers</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+                <span class="bp">self</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+
+<div class="viewcode-block" id="BaseResponse.copy"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.copy">[docs]</a>    <span class="k">def</span> <span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Returns a copy of self. &#39;&#39;&#39;</span>
+        <span class="n">copy</span> <span class="o">=</span> <span class="n">Response</span><span class="p">()</span>
+        <span class="n">copy</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span>
+        <span class="n">copy</span><span class="o">.</span><span class="n">_headers</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">[:])</span> <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
+        <span class="k">return</span> <span class="n">copy</span>
+</div>
+    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="p">,</span> <span class="s">&#39;close&#39;</span><span class="p">):</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseResponse.status_line"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.status_line">[docs]</a>    <span class="k">def</span> <span class="nf">status_line</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The HTTP status line as a string (e.g. ``404 Not Found``).&#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_line</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseResponse.status_code"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.status_code">[docs]</a>    <span class="k">def</span> <span class="nf">status_code</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; The HTTP status code as an integer (e.g. 404).&#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_code</span>
+</div>
+    <span class="k">def</span> <span class="nf">_set_status</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">status</span><span class="p">):</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
+            <span class="n">code</span><span class="p">,</span> <span class="n">status</span> <span class="o">=</span> <span class="n">status</span><span class="p">,</span> <span class="n">_HTTP_STATUS_LINES</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">status</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="s">&#39; &#39;</span> <span class="ow">in</span> <span class="n">status</span><span class="p">:</span>
+            <span class="n">status</span> <span class="o">=</span> <span class="n">status</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+            <span class="n">code</span>   <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">status</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">])</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#39;String status line without a reason phrase.&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="mi">100</span> <span class="o">&lt;=</span> <span class="n">code</span> <span class="o">&lt;=</span> <span class="mi">999</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#39;Status code out of range.&#39;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_status_code</span> <span class="o">=</span> <span class="n">code</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_status_line</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">status</span> <span class="ow">or</span> <span class="p">(</span><span class="s">&#39;</span><span class="si">%d</span><span class="s"> Unknown&#39;</span> <span class="o">%</span> <span class="n">code</span><span class="p">))</span>
+
+    <span class="k">def</span> <span class="nf">_get_status</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_line</span>
+
+    <span class="n">status</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="n">_get_status</span><span class="p">,</span> <span class="n">_set_status</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span>
+        <span class="sd">&#39;&#39;&#39; A writeable property to change the HTTP response status. It accepts</span>
+<span class="sd">            either a numeric code (100-999) or a string with a custom reason</span>
+<span class="sd">            phrase (e.g. &quot;404 Brain not found&quot;). Both :data:`status_line` and</span>
+<span class="sd">            :data:`status_code` are updated accordingly. The return value is</span>
+<span class="sd">            always a status string. &#39;&#39;&#39;</span><span class="p">)</span>
+    <span class="k">del</span> <span class="n">_get_status</span><span class="p">,</span> <span class="n">_set_status</span>
+
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseResponse.headers"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.headers">[docs]</a>    <span class="k">def</span> <span class="nf">headers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; An instance of :class:`HeaderDict`, a case-insensitive dict-like</span>
+<span class="sd">            view on the response headers. &#39;&#39;&#39;</span>
+        <span class="n">hdict</span> <span class="o">=</span> <span class="n">HeaderDict</span><span class="p">()</span>
+        <span class="n">hdict</span><span class="o">.</span><span class="n">dict</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span>
+        <span class="k">return</span> <span class="n">hdict</span>
+</div>
+    <span class="k">def</span> <span class="nf">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="k">return</span> <span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span>
+    <span class="k">def</span> <span class="nf">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>  <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">)]</span>
+    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>  <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">)][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">)]</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)]</span>
+
+<div class="viewcode-block" id="BaseResponse.get_header"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.get_header">[docs]</a>    <span class="k">def</span> <span class="nf">get_header</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Return the value of a previously defined header. If there is no</span>
+<span class="sd">            header with that name, return a default value. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="p">[</span><span class="n">default</span><span class="p">])[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+</div>
+<div class="viewcode-block" id="BaseResponse.set_header"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.set_header">[docs]</a>    <span class="k">def</span> <span class="nf">set_header</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Create a new response header, replacing any previously defined</span>
+<span class="sd">            headers with the same name. &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">)]</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)]</span>
+</div>
+<div class="viewcode-block" id="BaseResponse.add_header"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.add_header">[docs]</a>    <span class="k">def</span> <span class="nf">add_header</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add an additional response header, not removing duplicates. &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">_hkey</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">))</span>
+</div>
+<div class="viewcode-block" id="BaseResponse.iter_headers"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.iter_headers">[docs]</a>    <span class="k">def</span> <span class="nf">iter_headers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Yield (header, value) tuples, skipping headers that are not</span>
+<span class="sd">            allowed with the current response status code. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">headerlist</span>
+</div>
+    <span class="k">def</span> <span class="nf">wsgiheader</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&#39;The wsgiheader method is deprecated. See headerlist.&#39;</span><span class="p">)</span> <span class="c">#0.10</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">headerlist</span>
+
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseResponse.headerlist"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.headerlist">[docs]</a>    <span class="k">def</span> <span class="nf">headerlist</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; WSGI conform list of (header, value) tuples. &#39;&#39;&#39;</span>
+        <span class="n">out</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="n">headers</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_code</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">bad_headers</span><span class="p">:</span>
+            <span class="n">bad_headers</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">bad_headers</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_status_code</span><span class="p">]</span>
+            <span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span> <span class="k">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span> <span class="k">if</span> <span class="n">h</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">bad_headers</span><span class="p">]</span>
+        <span class="n">out</span> <span class="o">+=</span> <span class="p">[(</span><span class="n">name</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">vals</span> <span class="ow">in</span> <span class="n">headers</span> <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">vals</span><span class="p">]</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
+                <span class="n">out</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="s">&#39;Set-Cookie&#39;</span><span class="p">,</span> <span class="n">c</span><span class="o">.</span><span class="n">OutputString</span><span class="p">()))</span>
+        <span class="k">return</span> <span class="n">out</span>
+</div>
+    <span class="n">content_type</span> <span class="o">=</span> <span class="n">HeaderProperty</span><span class="p">(</span><span class="s">&#39;Content-Type&#39;</span><span class="p">)</span>
+    <span class="n">content_length</span> <span class="o">=</span> <span class="n">HeaderProperty</span><span class="p">(</span><span class="s">&#39;Content-Length&#39;</span><span class="p">,</span> <span class="n">reader</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
+
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseResponse.charset"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.charset">[docs]</a>    <span class="k">def</span> <span class="nf">charset</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Return the charset specified in the content-type header (default: utf8). &quot;&quot;&quot;</span>
+        <span class="k">if</span> <span class="s">&#39;charset=&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">content_type</span><span class="p">:</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">content_type</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;charset=&#39;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;;&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+        <span class="k">return</span> <span class="s">&#39;UTF-8&#39;</span>
+</div>
+    <span class="nd">@property</span>
+<div class="viewcode-block" id="BaseResponse.COOKIES"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.COOKIES">[docs]</a>    <span class="k">def</span> <span class="nf">COOKIES</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; A dict-like SimpleCookie instance. This should not be used directly.</span>
+<span class="sd">            See :meth:`set_cookie`. &quot;&quot;&quot;</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&#39;The COOKIES dict is deprecated. Use `set_cookie()` instead.&#39;</span><span class="p">)</span> <span class="c"># 0.10</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span> <span class="o">=</span> <span class="n">SimpleCookie</span><span class="p">()</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span>
+</div>
+<div class="viewcode-block" id="BaseResponse.set_cookie"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.set_cookie">[docs]</a>    <span class="k">def</span> <span class="nf">set_cookie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">secret</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Create a new cookie or replace an old one. If the `secret` parameter is</span>
+<span class="sd">            set, create a `Signed Cookie` (described below).</span>
+
+<span class="sd">            :param name: the name of the cookie.</span>
+<span class="sd">            :param value: the value of the cookie.</span>
+<span class="sd">            :param secret: a signature key required for signed cookies.</span>
+
+<span class="sd">            Additionally, this method accepts all RFC 2109 attributes that are</span>
+<span class="sd">            supported by :class:`cookie.Morsel`, including:</span>
+
+<span class="sd">            :param max_age: maximum age in seconds. (default: None)</span>
+<span class="sd">            :param expires: a datetime object or UNIX timestamp. (default: None)</span>
+<span class="sd">            :param domain: the domain that is allowed to read the cookie.</span>
+<span class="sd">              (default: current domain)</span>
+<span class="sd">            :param path: limits the cookie to a given path (default: current path)</span>
+<span class="sd">            :param secure: limit the cookie to HTTPS connections (default: off).</span>
+<span class="sd">            :param httponly: prevents client-side javascript to read this cookie</span>
+<span class="sd">              (default: off, requires Python 2.6 or newer).</span>
+
+<span class="sd">            If neither `expires` nor `max_age` is set (default), the cookie will</span>
+<span class="sd">            expire at the end of the browser session (as soon as the browser</span>
+<span class="sd">            window is closed).</span>
+
+<span class="sd">            Signed cookies may store any pickle-able object and are</span>
+<span class="sd">            cryptographically signed to prevent manipulation. Keep in mind that</span>
+<span class="sd">            cookies are limited to 4kb in most browsers.</span>
+
+<span class="sd">            Warning: Signed cookies are not encrypted (the client can still see</span>
+<span class="sd">            the content) and not copy-protected (the client can restore an old</span>
+<span class="sd">            cookie). The main intention is to make pickling and unpickling</span>
+<span class="sd">            save, not to store secret information at client side.</span>
+<span class="sd">        &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span> <span class="o">=</span> <span class="n">SimpleCookie</span><span class="p">()</span>
+
+        <span class="k">if</span> <span class="n">secret</span><span class="p">:</span>
+            <span class="n">value</span> <span class="o">=</span> <span class="n">touni</span><span class="p">(</span><span class="n">cookie_encode</span><span class="p">((</span><span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">),</span> <span class="n">secret</span><span class="p">))</span>
+        <span class="k">elif</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&#39;Secret key missing for non-string Cookie.&#39;</span><span class="p">)</span>
+
+        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">4096</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#39;Cookie value to long.&#39;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">options</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+            <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;max_age&#39;</span><span class="p">:</span>
+                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">timedelta</span><span class="p">):</span>
+                    <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">seconds</span> <span class="o">+</span> <span class="n">value</span><span class="o">.</span><span class="n">days</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">3600</span>
+            <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="s">&#39;expires&#39;</span><span class="p">:</span>
+                <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="n">datedate</span><span class="p">,</span> <span class="n">datetime</span><span class="p">)):</span>
+                    <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">timetuple</span><span class="p">()</span>
+                <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">)):</span>
+                    <span class="n">value</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">gmtime</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
+                <span class="n">value</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%a, </span><span class="si">%d</span><span class="s"> %b %Y %H:%M:%S GMT&quot;</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span><span class="p">[</span><span class="n">name</span><span class="p">][</span><span class="n">key</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;_&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)]</span> <span class="o">=</span> <span class="n">value</span>
+</div>
+<div class="viewcode-block" id="BaseResponse.delete_cookie"><a class="viewcode-back" href="../api.html#bottle.BaseResponse.delete_cookie">[docs]</a>    <span class="k">def</span> <span class="nf">delete_cookie</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Delete a cookie. Be sure to use the same `domain` and `path`</span>
+<span class="sd">            settings as used to create the cookie. &#39;&#39;&#39;</span>
+        <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;max_age&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
+        <span class="n">kwargs</span><span class="p">[</span><span class="s">&#39;expires&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+</div>
+    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">out</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
+        <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">headerlist</span><span class="p">:</span>
+            <span class="n">out</span> <span class="o">+=</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="se">\n</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">title</span><span class="p">(),</span> <span class="n">value</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
+        <span class="k">return</span> <span class="n">out</span>
+
+<span class="c">#: Thread-local storage for :class:`LocalRequest` and :class:`LocalResponse`</span>
+<span class="c">#: attributes.</span></div>
+<span class="n">_lctx</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">local</span><span class="p">()</span>
+
+<span class="k">def</span> <span class="nf">local_property</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">fget</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">_lctx</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
+        <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&quot;Request context not initialized.&quot;</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">fset</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span> <span class="nb">setattr</span><span class="p">(</span><span class="n">_lctx</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">fdel</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="nb">delattr</span><span class="p">(</span><span class="n">_lctx</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
+    <span class="k">return</span> <span class="nb">property</span><span class="p">(</span><span class="n">fget</span><span class="p">,</span> <span class="n">fset</span><span class="p">,</span> <span class="n">fdel</span><span class="p">,</span>
+        <span class="s">&#39;Thread-local property stored in :data:`_lctx.</span><span class="si">%s</span><span class="s">`&#39;</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span>
+
+
+<div class="viewcode-block" id="LocalRequest"><a class="viewcode-back" href="../api.html#bottle.LocalRequest">[docs]</a><span class="k">class</span> <span class="nc">LocalRequest</span><span class="p">(</span><span class="n">BaseRequest</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; A thread-local subclass of :class:`BaseRequest` with a different</span>
+<span class="sd">        set of attribues for each thread. There is usually only one global</span>
+<span class="sd">        instance of this class (:data:`request`). If accessed during a</span>
+<span class="sd">        request/response cycle, this instance always refers to the *current*</span>
+<span class="sd">        request (even on a multithreaded server). &#39;&#39;&#39;</span>
+    <span class="n">bind</span> <span class="o">=</span> <span class="n">BaseRequest</span><span class="o">.</span><span class="n">__init__</span>
+    <span class="n">environ</span> <span class="o">=</span> <span class="n">local_property</span><span class="p">(</span><span class="s">&#39;request_environ&#39;</span><span class="p">)</span>
+
+</div>
+<div class="viewcode-block" id="LocalResponse"><a class="viewcode-back" href="../api.html#bottle.LocalResponse">[docs]</a><span class="k">class</span> <span class="nc">LocalResponse</span><span class="p">(</span><span class="n">BaseResponse</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; A thread-local subclass of :class:`BaseResponse` with a different</span>
+<span class="sd">        set of attribues for each thread. There is usually only one global</span>
+<span class="sd">        instance of this class (:data:`response`). Its attributes are used</span>
+<span class="sd">        to build the HTTP response at the end of the request/response cycle.</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+    <span class="n">bind</span> <span class="o">=</span> <span class="n">BaseResponse</span><span class="o">.</span><span class="n">__init__</span>
+    <span class="n">_status_line</span> <span class="o">=</span> <span class="n">local_property</span><span class="p">(</span><span class="s">&#39;response_status_line&#39;</span><span class="p">)</span>
+    <span class="n">_status_code</span> <span class="o">=</span> <span class="n">local_property</span><span class="p">(</span><span class="s">&#39;response_status_code&#39;</span><span class="p">)</span>
+    <span class="n">_cookies</span>     <span class="o">=</span> <span class="n">local_property</span><span class="p">(</span><span class="s">&#39;response_cookies&#39;</span><span class="p">)</span>
+    <span class="n">_headers</span>     <span class="o">=</span> <span class="n">local_property</span><span class="p">(</span><span class="s">&#39;response_headers&#39;</span><span class="p">)</span>
+    <span class="n">body</span>         <span class="o">=</span> <span class="n">local_property</span><span class="p">(</span><span class="s">&#39;response_body&#39;</span><span class="p">)</span>
+</div>
+<span class="n">Request</span> <span class="o">=</span> <span class="n">BaseRequest</span>
+<span class="n">Response</span> <span class="o">=</span> <span class="n">BaseResponse</span>
+
+<div class="viewcode-block" id="HTTPResponse"><a class="viewcode-back" href="../api.html#bottle.HTTPResponse">[docs]</a><span class="k">class</span> <span class="nc">HTTPResponse</span><span class="p">(</span><span class="n">Response</span><span class="p">,</span> <span class="n">BottleException</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">header</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">header</span> <span class="ow">or</span> <span class="s">&#39;output&#39;</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span>
+            <span class="n">depr</span><span class="p">(</span><span class="s">&#39;Call signature changed (for the better)&#39;</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">header</span><span class="p">:</span> <span class="n">headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">header</span><span class="p">)</span>
+            <span class="k">if</span> <span class="s">&#39;output&#39;</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span> <span class="n">body</span> <span class="o">=</span> <span class="n">headers</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;output&#39;</span><span class="p">)</span>
+        <span class="nb">super</span><span class="p">(</span><span class="n">HTTPResponse</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">response</span><span class="p">):</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">_status_code</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_code</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">_status_line</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_line</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">_headers</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_headers</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">_cookies</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cookies</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">body</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">body</span>
+
+    <span class="k">def</span> <span class="nf">_output</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&#39;Use HTTPResponse.body instead of HTTPResponse.output&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">body</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">body</span> <span class="o">=</span> <span class="n">value</span>
+
+    <span class="n">output</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="n">_output</span><span class="p">,</span> <span class="n">_output</span><span class="p">,</span> <span class="n">doc</span><span class="o">=</span><span class="s">&#39;Alias for .body&#39;</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="HTTPError"><a class="viewcode-back" href="../api.html#bottle.HTTPError">[docs]</a><span class="k">class</span> <span class="nc">HTTPError</span><span class="p">(</span><span class="n">HTTPResponse</span><span class="p">):</span>
+    <span class="n">default_status</span> <span class="o">=</span> <span class="mi">500</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">body</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">exception</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">traceback</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">header</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">exception</span> <span class="o">=</span> <span class="n">exception</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">traceback</span> <span class="o">=</span> <span class="n">traceback</span>
+        <span class="nb">super</span><span class="p">(</span><span class="n">HTTPError</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">header</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">)</span>
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Plugins ######################################################################</span>
+<span class="c">###############################################################################</span>
+</div>
+<span class="k">class</span> <span class="nc">PluginError</span><span class="p">(</span><span class="n">BottleException</span><span class="p">):</span> <span class="k">pass</span>
+
+<span class="k">class</span> <span class="nc">JSONPlugin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;json&#39;</span>
+    <span class="n">api</span>  <span class="o">=</span> <span class="mi">2</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">json_dumps</span><span class="o">=</span><span class="n">json_dumps</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">json_dumps</span> <span class="o">=</span> <span class="n">json_dumps</span>
+
+    <span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">route</span><span class="p">):</span>
+        <span class="n">dumps</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">json_dumps</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">dumps</span><span class="p">:</span> <span class="k">return</span> <span class="n">callback</span>
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+            <span class="n">rv</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">rv</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
+                <span class="c">#Attempt to serialize, raises exception on failure</span>
+                <span class="n">json_response</span> <span class="o">=</span> <span class="n">dumps</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span>
+                <span class="c">#Set content type only if serialization succesful</span>
+                <span class="n">response</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=</span> <span class="s">&#39;application/json&#39;</span>
+                <span class="k">return</span> <span class="n">json_response</span>
+            <span class="k">return</span> <span class="n">rv</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+
+
+<span class="k">class</span> <span class="nc">HooksPlugin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;hooks&#39;</span>
+    <span class="n">api</span>  <span class="o">=</span> <span class="mi">2</span>
+
+    <span class="n">_names</span> <span class="o">=</span> <span class="s">&#39;before_request&#39;</span><span class="p">,</span> <span class="s">&#39;after_request&#39;</span><span class="p">,</span> <span class="s">&#39;app_reset&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">name</span><span class="p">,</span> <span class="p">[])</span> <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_names</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="bp">None</span>
+
+    <span class="k">def</span> <span class="nf">_empty</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="ow">not</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="p">[</span><span class="s">&#39;before_request&#39;</span><span class="p">]</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="p">[</span><span class="s">&#39;after_request&#39;</span><span class="p">])</span>
+
+    <span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
+
+    <span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Attach a callback to a hook. &#39;&#39;&#39;</span>
+        <span class="n">was_empty</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_empty</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="ow">and</span> <span class="n">was_empty</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_empty</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">func</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Remove a callback from a hook. &#39;&#39;&#39;</span>
+        <span class="n">was_empty</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_empty</span><span class="p">()</span>
+        <span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span> <span class="ow">and</span> <span class="n">func</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="p">[</span><span class="n">name</span><span class="p">]:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">was_empty</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_empty</span><span class="p">():</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">trigger</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Trigger a hook and return a list of results. &#39;&#39;&#39;</span>
+        <span class="n">hooks</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">hooks</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>
+        <span class="k">if</span> <span class="n">ka</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;reversed&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">):</span> <span class="n">hooks</span> <span class="o">=</span> <span class="n">hooks</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+        <span class="k">return</span> <span class="p">[</span><span class="n">hook</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span> <span class="k">for</span> <span class="n">hook</span> <span class="ow">in</span> <span class="n">hooks</span><span class="p">]</span>
+
+    <span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">route</span><span class="p">):</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_empty</span><span class="p">():</span> <span class="k">return</span> <span class="n">callback</span>
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">trigger</span><span class="p">(</span><span class="s">&#39;before_request&#39;</span><span class="p">)</span>
+            <span class="n">rv</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">trigger</span><span class="p">(</span><span class="s">&#39;after_request&#39;</span><span class="p">,</span> <span class="nb">reversed</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">rv</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+
+
+<span class="k">class</span> <span class="nc">TemplatePlugin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; This plugin applies the :func:`view` decorator to all routes with a</span>
+<span class="sd">        `template` config parameter. If the parameter is a tuple, the second</span>
+<span class="sd">        element must be a dict with additional options (e.g. `template_engine`)</span>
+<span class="sd">        or default variables for the template. &#39;&#39;&#39;</span>
+    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;template&#39;</span>
+    <span class="n">api</span>  <span class="o">=</span> <span class="mi">2</span>
+
+    <span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">route</span><span class="p">):</span>
+        <span class="n">conf</span> <span class="o">=</span> <span class="n">route</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;template&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">conf</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">))</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">conf</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">view</span><span class="p">(</span><span class="n">conf</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="o">**</span><span class="n">conf</span><span class="p">[</span><span class="mi">1</span><span class="p">])(</span><span class="n">callback</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">conf</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">and</span> <span class="s">&#39;template_opts&#39;</span> <span class="ow">in</span> <span class="n">route</span><span class="o">.</span><span class="n">config</span><span class="p">:</span>
+            <span class="n">depr</span><span class="p">(</span><span class="s">&#39;The `template_opts` parameter is deprecated.&#39;</span><span class="p">)</span> <span class="c">#0.9</span>
+            <span class="k">return</span> <span class="n">view</span><span class="p">(</span><span class="n">conf</span><span class="p">,</span> <span class="o">**</span><span class="n">route</span><span class="o">.</span><span class="n">config</span><span class="p">[</span><span class="s">&#39;template_opts&#39;</span><span class="p">])(</span><span class="n">callback</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">conf</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
+            <span class="k">return</span> <span class="n">view</span><span class="p">(</span><span class="n">conf</span><span class="p">)(</span><span class="n">callback</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">callback</span>
+
+
+<span class="c">#: Not a plugin, but part of the plugin API. TODO: Find a better place.</span>
+<span class="k">class</span> <span class="nc">_ImportRedirect</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">impmask</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Create a virtual package that redirects imports (see PEP 302). &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">impmask</span> <span class="o">=</span> <span class="n">impmask</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">module</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">imp</span><span class="o">.</span><span class="n">new_module</span><span class="p">(</span><span class="n">name</span><span class="p">))</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">module</span><span class="o">.</span><span class="n">__dict__</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s">&#39;__file__&#39;</span><span class="p">:</span> <span class="n">__file__</span><span class="p">,</span> <span class="s">&#39;__path__&#39;</span><span class="p">:</span> <span class="p">[],</span>
+                                    <span class="s">&#39;__all__&#39;</span><span class="p">:</span> <span class="p">[],</span> <span class="s">&#39;__loader__&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="p">})</span>
+        <span class="n">sys</span><span class="o">.</span><span class="n">meta_path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">find_module</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="k">if</span> <span class="s">&#39;.&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">fullname</span><span class="p">:</span> <span class="k">return</span>
+        <span class="n">packname</span><span class="p">,</span> <span class="n">modname</span> <span class="o">=</span> <span class="n">fullname</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">packname</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">:</span> <span class="k">return</span>
+        <span class="k">return</span> <span class="bp">self</span>
+
+    <span class="k">def</span> <span class="nf">load_module</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">fullname</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">:</span> <span class="k">return</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span>
+        <span class="n">packname</span><span class="p">,</span> <span class="n">modname</span> <span class="o">=</span> <span class="n">fullname</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+        <span class="n">realname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">impmask</span> <span class="o">%</span> <span class="n">modname</span>
+        <span class="nb">__import__</span><span class="p">(</span><span class="n">realname</span><span class="p">)</span>
+        <span class="n">module</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">realname</span><span class="p">]</span>
+        <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">module</span><span class="p">,</span> <span class="n">modname</span><span class="p">,</span> <span class="n">module</span><span class="p">)</span>
+        <span class="n">module</span><span class="o">.</span><span class="n">__loader__</span> <span class="o">=</span> <span class="bp">self</span>
+        <span class="k">return</span> <span class="n">module</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Common Utilities #############################################################</span>
+<span class="c">###############################################################################</span>
+
+
+<div class="viewcode-block" id="MultiDict"><a class="viewcode-back" href="../api.html#bottle.MultiDict">[docs]</a><span class="k">class</span> <span class="nc">MultiDict</span><span class="p">(</span><span class="n">DictMixin</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; This dict stores multiple values per key, but behaves exactly like a</span>
+<span class="sd">        normal dict in that it returns only the newest value for any given key.</span>
+<span class="sd">        There are special methods available to access the full list of values.</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">k</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">dict</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="p">[</span><span class="n">v</span><span class="p">])</span> <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">dict</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">k</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
+
+    <span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">iter</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span>
+    <span class="k">def</span> <span class="nf">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">keys</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
+
+    <span class="k">if</span> <span class="n">py3k</span><span class="p">:</span>
+        <span class="k">def</span> <span class="nf">values</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">(</span><span class="n">v</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">values</span><span class="p">())</span>
+        <span class="k">def</span> <span class="nf">items</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
+        <span class="k">def</span> <span class="nf">allitems</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+            <span class="k">return</span> <span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">vl</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vl</span><span class="p">)</span>
+        <span class="n">iterkeys</span> <span class="o">=</span> <span class="n">keys</span>
+        <span class="n">itervalues</span> <span class="o">=</span> <span class="n">values</span>
+        <span class="n">iteritems</span> <span class="o">=</span> <span class="n">items</span>
+        <span class="n">iterallitems</span> <span class="o">=</span> <span class="n">allitems</span>
+
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">def</span> <span class="nf">values</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">[</span><span class="n">v</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">values</span><span class="p">()]</span>
+        <span class="k">def</span> <span class="nf">items</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">[(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">items</span><span class="p">()]</span>
+        <span class="k">def</span> <span class="nf">iterkeys</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">iterkeys</span><span class="p">()</span>
+        <span class="k">def</span> <span class="nf">itervalues</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">(</span><span class="n">v</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">itervalues</span><span class="p">())</span>
+        <span class="k">def</span> <span class="nf">iteritems</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+            <span class="k">return</span> <span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">iteritems</span><span class="p">())</span>
+        <span class="k">def</span> <span class="nf">iterallitems</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+            <span class="k">return</span> <span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">vl</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">iteritems</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vl</span><span class="p">)</span>
+        <span class="k">def</span> <span class="nf">allitems</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+            <span class="k">return</span> <span class="p">[(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">vl</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">iteritems</span><span class="p">()</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vl</span><span class="p">]</span>
+
+<div class="viewcode-block" id="MultiDict.get"><a class="viewcode-back" href="../api.html#bottle.MultiDict.get">[docs]</a>    <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">index</span><span class="o">=-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Return the most recent value for a key.</span>
+
+<span class="sd">            :param default: The default value to be returned if the key is not</span>
+<span class="sd">                   present or the type conversion fails.</span>
+<span class="sd">            :param index: An index for the list of available values.</span>
+<span class="sd">            :param type: If defined, this callable is used to cast the value</span>
+<span class="sd">                    into a specific type. Exception are suppressed and result in</span>
+<span class="sd">                    the default value to be returned.</span>
+<span class="sd">        &#39;&#39;&#39;</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">val</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="n">index</span><span class="p">]</span>
+            <span class="k">return</span> <span class="nb">type</span><span class="p">(</span><span class="n">val</span><span class="p">)</span> <span class="k">if</span> <span class="nb">type</span> <span class="k">else</span> <span class="n">val</span>
+        <span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
+            <span class="k">pass</span>
+        <span class="k">return</span> <span class="n">default</span>
+</div>
+<div class="viewcode-block" id="MultiDict.append"><a class="viewcode-back" href="../api.html#bottle.MultiDict.append">[docs]</a>    <span class="k">def</span> <span class="nf">append</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add a new value to the list of values for this key. &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
+</div>
+<div class="viewcode-block" id="MultiDict.replace"><a class="viewcode-back" href="../api.html#bottle.MultiDict.replace">[docs]</a>    <span class="k">def</span> <span class="nf">replace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Replace the list of values with a single value. &#39;&#39;&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span>
+</div>
+<div class="viewcode-block" id="MultiDict.getall"><a class="viewcode-back" href="../api.html#bottle.MultiDict.getall">[docs]</a>    <span class="k">def</span> <span class="nf">getall</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Return a (possibly empty) list of values for a key. &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="ow">or</span> <span class="p">[]</span>
+
+    <span class="c">#: Aliases for WTForms to mimic other multi-dict APIs (Django)</span></div>
+    <span class="n">getone</span> <span class="o">=</span> <span class="n">get</span>
+    <span class="n">getlist</span> <span class="o">=</span> <span class="n">getall</span>
+
+
+</div>
+<div class="viewcode-block" id="FormsDict"><a class="viewcode-back" href="../api.html#bottle.FormsDict">[docs]</a><span class="k">class</span> <span class="nc">FormsDict</span><span class="p">(</span><span class="n">MultiDict</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; This :class:`MultiDict` subclass is used to store request form data.</span>
+<span class="sd">        Additionally to the normal dict-like item access methods (which return</span>
+<span class="sd">        unmodified data as native strings), this container also supports</span>
+<span class="sd">        attribute-like access to its values. Attributes are automatically de-</span>
+<span class="sd">        or recoded to match :attr:`input_encoding` (default: &#39;utf8&#39;). Missing</span>
+<span class="sd">        attributes default to an empty string. &#39;&#39;&#39;</span>
+
+    <span class="c">#: Encoding used for attribute values.</span>
+    <span class="n">input_encoding</span> <span class="o">=</span> <span class="s">&#39;utf8&#39;</span>
+    <span class="c">#: If true (default), unicode strings are first encoded with `latin1`</span>
+    <span class="c">#: and then decoded to match :attr:`input_encoding`.</span>
+    <span class="n">recode_unicode</span> <span class="o">=</span> <span class="bp">True</span>
+
+    <span class="k">def</span> <span class="nf">_fix</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">s</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">recode_unicode</span><span class="p">:</span> <span class="c"># Python 3 WSGI</span>
+            <span class="n">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">&#39;latin1&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span> <span class="c"># Python 2 WSGI</span>
+            <span class="k">return</span> <span class="n">s</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="n">encoding</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">input_encoding</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">s</span>
+
+<div class="viewcode-block" id="FormsDict.decode"><a class="viewcode-back" href="../api.html#bottle.FormsDict.decode">[docs]</a>    <span class="k">def</span> <span class="nf">decode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Returns a copy with all keys and values de- or recoded to match</span>
+<span class="sd">            :attr:`input_encoding`. Some libraries (e.g. WTForms) want a</span>
+<span class="sd">            unicode dictionary. &#39;&#39;&#39;</span>
+        <span class="n">copy</span> <span class="o">=</span> <span class="n">FormsDict</span><span class="p">()</span>
+        <span class="n">enc</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">input_encoding</span> <span class="o">=</span> <span class="n">encoding</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">input_encoding</span>
+        <span class="n">copy</span><span class="o">.</span><span class="n">recode_unicode</span> <span class="o">=</span> <span class="bp">False</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">allitems</span><span class="p">():</span>
+            <span class="n">copy</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_fix</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">enc</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fix</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">enc</span><span class="p">))</span>
+        <span class="k">return</span> <span class="n">copy</span>
+</div>
+    <span class="k">def</span> <span class="nf">getunicode</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fix</span><span class="p">(</span><span class="bp">self</span><span class="p">[</span><span class="n">name</span><span class="p">],</span> <span class="n">encoding</span><span class="p">)</span>
+        <span class="k">except</span> <span class="p">(</span><span class="ne">UnicodeError</span><span class="p">,</span> <span class="ne">KeyError</span><span class="p">):</span>
+            <span class="k">return</span> <span class="n">default</span>
+
+    <span class="k">def</span> <span class="nf">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="nb">unicode</span><span class="p">()):</span>
+        <span class="c"># Without this guard, pickle generates a cryptic TypeError:</span>
+        <span class="k">if</span> <span class="n">name</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;__&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">name</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;__&#39;</span><span class="p">):</span>
+            <span class="k">return</span> <span class="nb">super</span><span class="p">(</span><span class="n">FormsDict</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__getattr__</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">getunicode</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="n">default</span><span class="p">)</span>
+
+</div>
+<div class="viewcode-block" id="HeaderDict"><a class="viewcode-back" href="../api.html#bottle.HeaderDict">[docs]</a><span class="k">class</span> <span class="nc">HeaderDict</span><span class="p">(</span><span class="n">MultiDict</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; A case-insensitive version of :class:`MultiDict` that defaults to</span>
+<span class="sd">        replace the old value instead of appending it. &quot;&quot;&quot;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">dict</span> <span class="o">=</span> <span class="p">{}</span>
+        <span class="k">if</span> <span class="n">a</span> <span class="ow">or</span> <span class="n">ka</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span>
+    <span class="k">def</span> <span class="nf">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span>
+    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">)][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)]</span>
+    <span class="k">def</span> <span class="nf">append</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">))</span>
+    <span class="k">def</span> <span class="nf">replace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">)]</span> <span class="o">=</span> <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">value</span><span class="p">)]</span>
+    <span class="k">def</span> <span class="nf">getall</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">))</span> <span class="ow">or</span> <span class="p">[]</span>
+    <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">index</span><span class="o">=-</span><span class="mi">1</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">MultiDict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_hkey</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">default</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">names</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="p">[</span><span class="n">_hkey</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">names</span><span class="p">]:</span>
+            <span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">:</span>
+                <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>
+
+</div>
+<div class="viewcode-block" id="WSGIHeaderDict"><a class="viewcode-back" href="../api.html#bottle.WSGIHeaderDict">[docs]</a><span class="k">class</span> <span class="nc">WSGIHeaderDict</span><span class="p">(</span><span class="n">DictMixin</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; This dict-like class wraps a WSGI environ dict and provides convenient</span>
+<span class="sd">        access to HTTP_* fields. Keys and values are native strings</span>
+<span class="sd">        (2.x bytes or 3.x unicode) and keys are case-insensitive. If the WSGI</span>
+<span class="sd">        environment contains non-native string values, these are de- or encoded</span>
+<span class="sd">        using a lossless &#39;latin1&#39; character set.</span>
+
+<span class="sd">        The API will remain stable even on changes to the relevant PEPs.</span>
+<span class="sd">        Currently PEP 333, 444 and 3333 are supported. (PEP 444 is the only one</span>
+<span class="sd">        that uses non-native strings.)</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+    <span class="c">#: List of keys that do not have a ``HTTP_`` prefix.</span>
+    <span class="n">cgikeys</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;CONTENT_TYPE&#39;</span><span class="p">,</span> <span class="s">&#39;CONTENT_LENGTH&#39;</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">environ</span> <span class="o">=</span> <span class="n">environ</span>
+
+    <span class="k">def</span> <span class="nf">_ekey</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Translate header field name to CGI/WSGI environ key. &#39;&#39;&#39;</span>
+        <span class="n">key</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;-&#39;</span><span class="p">,</span><span class="s">&#39;_&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
+        <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">cgikeys</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">key</span>
+        <span class="k">return</span> <span class="s">&#39;HTTP_&#39;</span> <span class="o">+</span> <span class="n">key</span>
+
+<div class="viewcode-block" id="WSGIHeaderDict.raw"><a class="viewcode-back" href="../api.html#bottle.WSGIHeaderDict.raw">[docs]</a>    <span class="k">def</span> <span class="nf">raw</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Return the header value as is (may be bytes or unicode). &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_ekey</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">default</span><span class="p">)</span>
+</div>
+    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">tonat</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_ekey</span><span class="p">(</span><span class="n">key</span><span class="p">)],</span> <span class="s">&#39;latin1&#39;</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> is read-only.&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__delitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+        <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> is read-only.&quot;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span><span class="p">:</span>
+            <span class="k">if</span> <span class="n">key</span><span class="p">[:</span><span class="mi">5</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;HTTP_&#39;</span><span class="p">:</span>
+                <span class="k">yield</span> <span class="n">key</span><span class="p">[</span><span class="mi">5</span><span class="p">:]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;_&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
+            <span class="k">elif</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">cgikeys</span><span class="p">:</span>
+                <span class="k">yield</span> <span class="n">key</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;_&#39;</span><span class="p">,</span> <span class="s">&#39;-&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">title</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">keys</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
+    <span class="k">def</span> <span class="nf">__contains__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ekey</span><span class="p">(</span><span class="n">key</span><span class="p">)</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span>
+
+</div>
+<span class="k">class</span> <span class="nc">ConfigDict</span><span class="p">(</span><span class="nb">dict</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; A dict-subclass with some extras: You can access keys like attributes.</span>
+<span class="sd">        Uppercase attributes create new ConfigDicts and act as name-spaces.</span>
+<span class="sd">        Other missing attributes return None. Calling a ConfigDict updates its</span>
+<span class="sd">        values and returns itself.</span>
+
+<span class="sd">        &gt;&gt;&gt; cfg = ConfigDict()</span>
+<span class="sd">        &gt;&gt;&gt; cfg.Namespace.value = 5</span>
+<span class="sd">        &gt;&gt;&gt; cfg.OtherNamespace(a=1, b=2)</span>
+<span class="sd">        &gt;&gt;&gt; cfg</span>
+<span class="sd">        {&#39;Namespace&#39;: {&#39;value&#39;: 5}, &#39;OtherNamespace&#39;: {&#39;a&#39;: 1, &#39;b&#39;: 2}}</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span> <span class="ow">and</span> <span class="n">key</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">isupper</span><span class="p">():</span>
+            <span class="bp">self</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">ConfigDict</span><span class="p">()</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__setattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
+        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s">&#39;Read-only attribute.&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span> <span class="ow">and</span> <span class="bp">self</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="p">[</span><span class="n">key</span><span class="p">],</span> <span class="n">ConfigDict</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">AttributeError</span><span class="p">(</span><span class="s">&#39;Non-empty namespace attribute.&#39;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
+
+    <span class="k">def</span> <span class="nf">__delattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+        <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span> <span class="k">del</span> <span class="bp">self</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
+
+    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">dict</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span>
+
+
+<div class="viewcode-block" id="AppStack"><a class="viewcode-back" href="../api.html#bottle.AppStack">[docs]</a><span class="k">class</span> <span class="nc">AppStack</span><span class="p">(</span><span class="nb">list</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; A stack-like list. Calling it returns the head of the stack. &quot;&quot;&quot;</span>
+
+    <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Return the current default application. &quot;&quot;&quot;</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+
+<div class="viewcode-block" id="AppStack.push"><a class="viewcode-back" href="../api.html#bottle.AppStack.push">[docs]</a>    <span class="k">def</span> <span class="nf">push</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Add a new :class:`Bottle` instance to the stack &quot;&quot;&quot;</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">Bottle</span><span class="p">):</span>
+            <span class="n">value</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">value</span>
+
+</div></div>
+<span class="k">class</span> <span class="nc">WSGIFileWrapper</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fp</span><span class="p">,</span> <span class="n">buffer_size</span><span class="o">=</span><span class="mi">1024</span><span class="o">*</span><span class="mi">64</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">fp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer_size</span> <span class="o">=</span> <span class="n">fp</span><span class="p">,</span> <span class="n">buffer_size</span>
+        <span class="k">for</span> <span class="n">attr</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;fileno&#39;</span><span class="p">,</span> <span class="s">&#39;close&#39;</span><span class="p">,</span> <span class="s">&#39;read&#39;</span><span class="p">,</span> <span class="s">&#39;readlines&#39;</span><span class="p">,</span> <span class="s">&#39;tell&#39;</span><span class="p">,</span> <span class="s">&#39;seek&#39;</span><span class="p">):</span>
+            <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">attr</span><span class="p">):</span> <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">,</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">attr</span><span class="p">))</span>
+
+    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">buff</span><span class="p">,</span> <span class="n">read</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">buffer_size</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">read</span>
+        <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
+            <span class="n">part</span> <span class="o">=</span> <span class="n">read</span><span class="p">(</span><span class="n">buff</span><span class="p">)</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">part</span><span class="p">:</span> <span class="k">return</span>
+            <span class="k">yield</span> <span class="n">part</span>
+
+
+<div class="viewcode-block" id="ResourceManager"><a class="viewcode-back" href="../api.html#bottle.ResourceManager">[docs]</a><span class="k">class</span> <span class="nc">ResourceManager</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; This class manages a list of search paths and helps to find and open</span>
+<span class="sd">        application-bound resources (files).</span>
+
+<span class="sd">        :param base: default value for :meth:`add_path` calls.</span>
+<span class="sd">        :param opener: callable used to open resources.</span>
+<span class="sd">        :param cachemode: controls which lookups are cached. One of &#39;all&#39;,</span>
+<span class="sd">                         &#39;found&#39; or &#39;none&#39;.</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="s">&#39;./&#39;</span><span class="p">,</span> <span class="n">opener</span><span class="o">=</span><span class="nb">open</span><span class="p">,</span> <span class="n">cachemode</span><span class="o">=</span><span class="s">&#39;all&#39;</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">opener</span> <span class="o">=</span> <span class="nb">open</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">base</span> <span class="o">=</span> <span class="n">base</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">cachemode</span> <span class="o">=</span> <span class="n">cachemode</span>
+
+        <span class="c">#: A list of search paths. See :meth:`add_path` for details.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="c">#: A cache for resolved paths. ``res.cache.clear()`` clears the cache.</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="p">{}</span>
+
+<div class="viewcode-block" id="ResourceManager.add_path"><a class="viewcode-back" href="../api.html#bottle.ResourceManager.add_path">[docs]</a>    <span class="k">def</span> <span class="nf">add_path</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">base</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">create</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Add a new path to the list of search paths. Return False if the</span>
+<span class="sd">            path does not exist.</span>
+
+<span class="sd">            :param path: The new search path. Relative paths are turned into</span>
+<span class="sd">                an absolute and normalized form. If the path looks like a file</span>
+<span class="sd">                (not ending in `/`), the filename is stripped off.</span>
+<span class="sd">            :param base: Path used to absolutize relative search paths.</span>
+<span class="sd">                Defaults to :attr:`base` which defaults to ``os.getcwd()``.</span>
+<span class="sd">            :param index: Position within the list of search paths. Defaults</span>
+<span class="sd">                to last index (appends to the list).</span>
+
+<span class="sd">            The `base` parameter makes it easy to reference files installed</span>
+<span class="sd">            along with a python module or package::</span>
+
+<span class="sd">                res.add_path(&#39;./resources/&#39;, __file__)</span>
+<span class="sd">        &#39;&#39;&#39;</span>
+        <span class="n">base</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">base</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">base</span><span class="p">))</span>
+        <span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">path</span><span class="p">)))</span>
+        <span class="n">path</span> <span class="o">+=</span> <span class="n">os</span><span class="o">.</span><span class="n">sep</span>
+        <span class="k">if</span> <span class="n">path</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">create</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+            <span class="n">os</span><span class="o">.</span><span class="n">makedirs</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">index</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="n">index</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
+        <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+</div>
+    <span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Iterate over all existing files in all registered paths. &#39;&#39;&#39;</span>
+        <span class="n">search</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">[:]</span>
+        <span class="k">while</span> <span class="n">search</span><span class="p">:</span>
+            <span class="n">path</span> <span class="o">=</span> <span class="n">search</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">path</span><span class="p">):</span> <span class="k">continue</span>
+            <span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">listdir</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+                <span class="n">full</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="n">full</span><span class="p">):</span> <span class="n">search</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">full</span><span class="p">)</span>
+                <span class="k">else</span><span class="p">:</span> <span class="k">yield</span> <span class="n">full</span>
+
+<div class="viewcode-block" id="ResourceManager.lookup"><a class="viewcode-back" href="../api.html#bottle.ResourceManager.lookup">[docs]</a>    <span class="k">def</span> <span class="nf">lookup</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Search for a resource and return an absolute file path, or `None`.</span>
+
+<span class="sd">            The :attr:`path` list is searched in order. The first match is</span>
+<span class="sd">            returend. Symlinks are followed. The result is cached to speed up</span>
+<span class="sd">            future lookups. &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="n">name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="ow">or</span> <span class="n">DEBUG</span><span class="p">:</span>
+            <span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">path</span><span class="p">:</span>
+                <span class="n">fpath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">name</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">fpath</span><span class="p">):</span>
+                    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cachemode</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;all&#39;</span><span class="p">,</span> <span class="s">&#39;found&#39;</span><span class="p">):</span>
+                        <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">fpath</span>
+                    <span class="k">return</span> <span class="n">fpath</span>
+            <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cachemode</span> <span class="o">==</span> <span class="s">&#39;all&#39;</span><span class="p">:</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="n">name</span><span class="p">]</span>
+</div>
+<div class="viewcode-block" id="ResourceManager.open"><a class="viewcode-back" href="../api.html#bottle.ResourceManager.open">[docs]</a>    <span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s">&#39;r&#39;</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Find a resource and return a file object, or raise IOError. &#39;&#39;&#39;</span>
+        <span class="n">fname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookup</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">fname</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">IOError</span><span class="p">(</span><span class="s">&quot;Resource </span><span class="si">%r</span><span class="s"> not found.&quot;</span> <span class="o">%</span> <span class="n">name</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">opener</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="n">mode</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Application Helper ###########################################################</span>
+<span class="c">###############################################################################</span>
+
+</div></div>
+<span class="k">def</span> <span class="nf">abort</span><span class="p">(</span><span class="n">code</span><span class="o">=</span><span class="mi">500</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s">&#39;Unknown Error: Application stopped.&#39;</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Aborts execution and causes a HTTP error. &quot;&quot;&quot;</span>
+    <span class="k">raise</span> <span class="n">HTTPError</span><span class="p">(</span><span class="n">code</span><span class="p">,</span> <span class="n">text</span><span class="p">)</span>
+
+
+<span class="k">def</span> <span class="nf">redirect</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">code</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Aborts execution and causes a 303 or 302 redirect, depending on</span>
+<span class="sd">        the HTTP protocol version. &quot;&quot;&quot;</span>
+    <span class="k">if</span> <span class="n">code</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
+        <span class="n">code</span> <span class="o">=</span> <span class="mi">303</span> <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SERVER_PROTOCOL&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s">&quot;HTTP/1.1&quot;</span> <span class="k">else</span> <span class="mi">302</span>
+    <span class="n">location</span> <span class="o">=</span> <span class="n">urljoin</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">url</span><span class="p">,</span> <span class="n">url</span><span class="p">)</span>
+    <span class="k">raise</span> <span class="n">HTTPResponse</span><span class="p">(</span><span class="s">&quot;&quot;</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="n">code</span><span class="p">,</span> <span class="n">Location</span><span class="o">=</span><span class="n">location</span><span class="p">)</span>
+
+
+<span class="k">def</span> <span class="nf">_file_iter_range</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">maxread</span><span class="o">=</span><span class="mi">1024</span><span class="o">*</span><span class="mi">1024</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Yield chunks from a range in a file. No chunk is bigger than maxread.&#39;&#39;&#39;</span>
+    <span class="n">fp</span><span class="o">.</span><span class="n">seek</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
+    <span class="k">while</span> <span class="nb">bytes</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
+        <span class="n">part</span> <span class="o">=</span> <span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="n">maxread</span><span class="p">))</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">part</span><span class="p">:</span> <span class="k">break</span>
+        <span class="nb">bytes</span> <span class="o">-=</span> <span class="nb">len</span><span class="p">(</span><span class="n">part</span><span class="p">)</span>
+        <span class="k">yield</span> <span class="n">part</span>
+
+
+<span class="k">def</span> <span class="nf">static_file</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">root</span><span class="p">,</span> <span class="n">mimetype</span><span class="o">=</span><span class="s">&#39;auto&#39;</span><span class="p">,</span> <span class="n">download</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Open a file in a safe way and return :exc:`HTTPResponse` with status</span>
+<span class="sd">        code 200, 305, 401 or 404. Set Content-Type, Content-Encoding,</span>
+<span class="sd">        Content-Length and Last-Modified header. Obey If-Modified-Since header</span>
+<span class="sd">        and HEAD requests.</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+    <span class="n">root</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">root</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">sep</span>
+    <span class="n">filename</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">filename</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s">&#39;/</span><span class="se">\\</span><span class="s">&#39;</span><span class="p">)))</span>
+    <span class="n">headers</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
+
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">filename</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">root</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">403</span><span class="p">,</span> <span class="s">&quot;Access denied.&quot;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="s">&quot;File does not exist.&quot;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">access</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">R_OK</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">403</span><span class="p">,</span> <span class="s">&quot;You do not have permission to access this file.&quot;</span><span class="p">)</span>
+
+    <span class="k">if</span> <span class="n">mimetype</span> <span class="o">==</span> <span class="s">&#39;auto&#39;</span><span class="p">:</span>
+        <span class="n">mimetype</span><span class="p">,</span> <span class="n">encoding</span> <span class="o">=</span> <span class="n">mimetypes</span><span class="o">.</span><span class="n">guess_type</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">mimetype</span><span class="p">:</span> <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Content-Type&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">mimetype</span>
+        <span class="k">if</span> <span class="n">encoding</span><span class="p">:</span> <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Content-Encoding&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">encoding</span>
+    <span class="k">elif</span> <span class="n">mimetype</span><span class="p">:</span>
+        <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Content-Type&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">mimetype</span>
+
+    <span class="k">if</span> <span class="n">download</span><span class="p">:</span>
+        <span class="n">download</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">filename</span> <span class="k">if</span> <span class="n">download</span> <span class="o">==</span> <span class="bp">True</span> <span class="k">else</span> <span class="n">download</span><span class="p">)</span>
+        <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Content-Disposition&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;attachment; filename=&quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">download</span>
+
+    <span class="n">stats</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
+    <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Content-Length&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">clen</span> <span class="o">=</span> <span class="n">stats</span><span class="o">.</span><span class="n">st_size</span>
+    <span class="n">lm</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%a, </span><span class="si">%d</span><span class="s"> %b %Y %H:%M:%S GMT&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">gmtime</span><span class="p">(</span><span class="n">stats</span><span class="o">.</span><span class="n">st_mtime</span><span class="p">))</span>
+    <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Last-Modified&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lm</span>
+
+    <span class="n">ims</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_IF_MODIFIED_SINCE&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">ims</span><span class="p">:</span>
+        <span class="n">ims</span> <span class="o">=</span> <span class="n">parse_date</span><span class="p">(</span><span class="n">ims</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;;&quot;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
+    <span class="k">if</span> <span class="n">ims</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="n">ims</span> <span class="o">&gt;=</span> <span class="nb">int</span><span class="p">(</span><span class="n">stats</span><span class="o">.</span><span class="n">st_mtime</span><span class="p">):</span>
+        <span class="n">headers</span><span class="p">[</span><span class="s">&#39;Date&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%a, </span><span class="si">%d</span><span class="s"> %b %Y %H:%M:%S GMT&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">gmtime</span><span class="p">())</span>
+        <span class="k">return</span> <span class="n">HTTPResponse</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="mi">304</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">)</span>
+
+    <span class="n">body</span> <span class="o">=</span> <span class="s">&#39;&#39;</span> <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">&#39;HEAD&#39;</span> <span class="k">else</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">)</span>
+
+    <span class="n">headers</span><span class="p">[</span><span class="s">&quot;Accept-Ranges&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;bytes&quot;</span>
+    <span class="n">ranges</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;HTTP_RANGE&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="s">&#39;HTTP_RANGE&#39;</span> <span class="ow">in</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">:</span>
+        <span class="n">ranges</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">parse_range_header</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s">&#39;HTTP_RANGE&#39;</span><span class="p">],</span> <span class="n">clen</span><span class="p">))</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">ranges</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">416</span><span class="p">,</span> <span class="s">&quot;Requested Range Not Satisfiable&quot;</span><span class="p">)</span>
+        <span class="n">offset</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="n">ranges</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
+        <span class="n">headers</span><span class="p">[</span><span class="s">&quot;Content-Range&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;bytes </span><span class="si">%d</span><span class="s">-</span><span class="si">%d</span><span class="s">/</span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">offset</span><span class="p">,</span> <span class="n">end</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="n">clen</span><span class="p">)</span>
+        <span class="n">headers</span><span class="p">[</span><span class="s">&quot;Content-Length&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">end</span><span class="o">-</span><span class="n">offset</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">body</span><span class="p">:</span> <span class="n">body</span> <span class="o">=</span> <span class="n">_file_iter_range</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">offset</span><span class="p">,</span> <span class="n">end</span><span class="o">-</span><span class="n">offset</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">HTTPResponse</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">status</span><span class="o">=</span><span class="mi">206</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">HTTPResponse</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="o">**</span><span class="n">headers</span><span class="p">)</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># HTTP Utilities and MISC (TODO) ###############################################</span>
+<span class="c">###############################################################################</span>
+
+
+<div class="viewcode-block" id="debug"><a class="viewcode-back" href="../api.html#bottle.debug">[docs]</a><span class="k">def</span> <span class="nf">debug</span><span class="p">(</span><span class="n">mode</span><span class="o">=</span><span class="bp">True</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Change the debug level.</span>
+<span class="sd">    There is only one debug level supported at the moment.&quot;&quot;&quot;</span>
+    <span class="k">global</span> <span class="n">DEBUG</span>
+    <span class="n">DEBUG</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">mode</span><span class="p">)</span>
+
+</div>
+<div class="viewcode-block" id="parse_date"><a class="viewcode-back" href="../api.html#bottle.parse_date">[docs]</a><span class="k">def</span> <span class="nf">parse_date</span><span class="p">(</span><span class="n">ims</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Parse rfc1123, rfc850 and asctime timestamps and return UTC epoch. &quot;&quot;&quot;</span>
+    <span class="k">try</span><span class="p">:</span>
+        <span class="n">ts</span> <span class="o">=</span> <span class="n">email</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">parsedate_tz</span><span class="p">(</span><span class="n">ims</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">time</span><span class="o">.</span><span class="n">mktime</span><span class="p">(</span><span class="n">ts</span><span class="p">[:</span><span class="mi">8</span><span class="p">]</span> <span class="o">+</span> <span class="p">(</span><span class="mi">0</span><span class="p">,))</span> <span class="o">-</span> <span class="p">(</span><span class="n">ts</span><span class="p">[</span><span class="mi">9</span><span class="p">]</span> <span class="ow">or</span> <span class="mi">0</span><span class="p">)</span> <span class="o">-</span> <span class="n">time</span><span class="o">.</span><span class="n">timezone</span>
+    <span class="k">except</span> <span class="p">(</span><span class="ne">TypeError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="ne">IndexError</span><span class="p">,</span> <span class="ne">OverflowError</span><span class="p">):</span>
+        <span class="k">return</span> <span class="bp">None</span>
+
+</div>
+<div class="viewcode-block" id="parse_auth"><a class="viewcode-back" href="../api.html#bottle.parse_auth">[docs]</a><span class="k">def</span> <span class="nf">parse_auth</span><span class="p">(</span><span class="n">header</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Parse rfc2617 HTTP authentication header string (basic) and return (user,pass) tuple or None&quot;&quot;&quot;</span>
+    <span class="k">try</span><span class="p">:</span>
+        <span class="n">method</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="n">header</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">method</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s">&#39;basic&#39;</span><span class="p">:</span>
+            <span class="n">user</span><span class="p">,</span> <span class="n">pwd</span> <span class="o">=</span> <span class="n">touni</span><span class="p">(</span><span class="n">base64</span><span class="o">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">tob</span><span class="p">(</span><span class="n">data</span><span class="p">)))</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">user</span><span class="p">,</span> <span class="n">pwd</span>
+    <span class="k">except</span> <span class="p">(</span><span class="ne">KeyError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">):</span>
+        <span class="k">return</span> <span class="bp">None</span>
+</div>
+<span class="k">def</span> <span class="nf">parse_range_header</span><span class="p">(</span><span class="n">header</span><span class="p">,</span> <span class="n">maxlen</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Yield (start, end) ranges parsed from a HTTP Range header. Skip</span>
+<span class="sd">        unsatisfiable ranges. The end index is non-inclusive.&#39;&#39;&#39;</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">header</span> <span class="ow">or</span> <span class="n">header</span><span class="p">[:</span><span class="mi">6</span><span class="p">]</span> <span class="o">!=</span> <span class="s">&#39;bytes=&#39;</span><span class="p">:</span> <span class="k">return</span>
+    <span class="n">ranges</span> <span class="o">=</span> <span class="p">[</span><span class="n">r</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;-&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="n">header</span><span class="p">[</span><span class="mi">6</span><span class="p">:]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;,&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="s">&#39;-&#39;</span> <span class="ow">in</span> <span class="n">r</span><span class="p">]</span>
+    <span class="k">for</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">:</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">start</span><span class="p">:</span>  <span class="c"># bytes=-100    -&gt; last 100 bytes</span>
+                <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">maxlen</span><span class="o">-</span><span class="nb">int</span><span class="p">(</span><span class="n">end</span><span class="p">)),</span> <span class="n">maxlen</span>
+            <span class="k">elif</span> <span class="ow">not</span> <span class="n">end</span><span class="p">:</span>  <span class="c"># bytes=100-    -&gt; all but the first 99 bytes</span>
+                <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">start</span><span class="p">),</span> <span class="n">maxlen</span>
+            <span class="k">else</span><span class="p">:</span>          <span class="c"># bytes=100-200 -&gt; bytes 100-200 (inclusive)</span>
+                <span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">start</span><span class="p">),</span> <span class="nb">min</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">end</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="n">maxlen</span><span class="p">)</span>
+            <span class="k">if</span> <span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">start</span> <span class="o">&lt;</span> <span class="n">end</span> <span class="o">&lt;=</span> <span class="n">maxlen</span><span class="p">:</span>
+                <span class="k">yield</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span>
+        <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
+            <span class="k">pass</span>
+
+<span class="k">def</span> <span class="nf">_parse_qsl</span><span class="p">(</span><span class="n">qs</span><span class="p">):</span>
+    <span class="n">r</span> <span class="o">=</span> <span class="p">[]</span>
+    <span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">qs</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;;&#39;</span><span class="p">,</span><span class="s">&#39;&amp;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;&amp;&#39;</span><span class="p">):</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">pair</span><span class="p">:</span> <span class="k">continue</span>
+        <span class="n">nv</span> <span class="o">=</span> <span class="n">pair</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;=&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">nv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">:</span> <span class="n">nv</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">)</span>
+        <span class="n">key</span> <span class="o">=</span> <span class="n">urlunquote</span><span class="p">(</span><span class="n">nv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="s">&#39; &#39;</span><span class="p">))</span>
+        <span class="n">value</span> <span class="o">=</span> <span class="n">urlunquote</span><span class="p">(</span><span class="n">nv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;+&#39;</span><span class="p">,</span> <span class="s">&#39; &#39;</span><span class="p">))</span>
+        <span class="n">r</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span>
+    <span class="k">return</span> <span class="n">r</span>
+
+<span class="k">def</span> <span class="nf">_lscmp</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Compares two strings in a cryptographically safe way:</span>
+<span class="sd">        Runtime is not affected by length of common prefix. &#39;&#39;&#39;</span>
+    <span class="k">return</span> <span class="ow">not</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">0</span> <span class="k">if</span> <span class="n">x</span><span class="o">==</span><span class="n">y</span> <span class="k">else</span> <span class="mi">1</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">))</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
+
+
+<div class="viewcode-block" id="cookie_encode"><a class="viewcode-back" href="../api.html#bottle.cookie_encode">[docs]</a><span class="k">def</span> <span class="nf">cookie_encode</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Encode and sign a pickle-able object. Return a (byte) string &#39;&#39;&#39;</span>
+    <span class="n">msg</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">pickle</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">))</span>
+    <span class="n">sig</span> <span class="o">=</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">hmac</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">tob</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">msg</span><span class="p">)</span><span class="o">.</span><span class="n">digest</span><span class="p">())</span>
+    <span class="k">return</span> <span class="n">tob</span><span class="p">(</span><span class="s">&#39;!&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="n">sig</span> <span class="o">+</span> <span class="n">tob</span><span class="p">(</span><span class="s">&#39;?&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="n">msg</span>
+
+</div>
+<div class="viewcode-block" id="cookie_decode"><a class="viewcode-back" href="../api.html#bottle.cookie_decode">[docs]</a><span class="k">def</span> <span class="nf">cookie_decode</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Verify and decode an encoded string. Return an object or None.&#39;&#39;&#39;</span>
+    <span class="n">data</span> <span class="o">=</span> <span class="n">tob</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">cookie_is_encoded</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
+        <span class="n">sig</span><span class="p">,</span> <span class="n">msg</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">tob</span><span class="p">(</span><span class="s">&#39;?&#39;</span><span class="p">),</span> <span class="mi">1</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">_lscmp</span><span class="p">(</span><span class="n">sig</span><span class="p">[</span><span class="mi">1</span><span class="p">:],</span> <span class="n">base64</span><span class="o">.</span><span class="n">b64encode</span><span class="p">(</span><span class="n">hmac</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">tob</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">msg</span><span class="p">)</span><span class="o">.</span><span class="n">digest</span><span class="p">())):</span>
+            <span class="k">return</span> <span class="n">pickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">base64</span><span class="o">.</span><span class="n">b64decode</span><span class="p">(</span><span class="n">msg</span><span class="p">))</span>
+    <span class="k">return</span> <span class="bp">None</span>
+
+</div>
+<div class="viewcode-block" id="cookie_is_encoded"><a class="viewcode-back" href="../api.html#bottle.cookie_is_encoded">[docs]</a><span class="k">def</span> <span class="nf">cookie_is_encoded</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Return True if the argument looks like a encoded cookie.&#39;&#39;&#39;</span>
+    <span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">tob</span><span class="p">(</span><span class="s">&#39;!&#39;</span><span class="p">))</span> <span class="ow">and</span> <span class="n">tob</span><span class="p">(</span><span class="s">&#39;?&#39;</span><span class="p">)</span> <span class="ow">in</span> <span class="n">data</span><span class="p">)</span>
+
+</div>
+<span class="k">def</span> <span class="nf">html_escape</span><span class="p">(</span><span class="n">string</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Escape HTML special characters ``&amp;&lt;&gt;`` and quotes ``&#39;&quot;``. &#39;&#39;&#39;</span>
+    <span class="k">return</span> <span class="n">string</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&amp;&#39;</span><span class="p">,</span><span class="s">&#39;&amp;amp;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&lt;&#39;</span><span class="p">,</span><span class="s">&#39;&amp;lt;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&gt;&#39;</span><span class="p">,</span><span class="s">&#39;&amp;gt;&#39;</span><span class="p">)</span>\
+                 <span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">,</span><span class="s">&#39;&amp;quot;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&quot;&#39;&quot;</span><span class="p">,</span><span class="s">&#39;&amp;#039;&#39;</span><span class="p">)</span>
+
+
+<span class="k">def</span> <span class="nf">html_quote</span><span class="p">(</span><span class="n">string</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Escape and quote a string to be used as an HTTP attribute.&#39;&#39;&#39;</span>
+    <span class="k">return</span> <span class="s">&#39;&quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">html_escape</span><span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">,</span><span class="s">&#39;%#10;&#39;</span><span class="p">)</span>\
+                    <span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\r</span><span class="s">&#39;</span><span class="p">,</span><span class="s">&#39;&amp;#13;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\t</span><span class="s">&#39;</span><span class="p">,</span><span class="s">&#39;&amp;#9;&#39;</span><span class="p">)</span>
+
+
+<div class="viewcode-block" id="yieldroutes"><a class="viewcode-back" href="../api.html#bottle.yieldroutes">[docs]</a><span class="k">def</span> <span class="nf">yieldroutes</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Return a generator for routes that match the signature (name, args)</span>
+<span class="sd">    of the func parameter. This may yield more than one route if the function</span>
+<span class="sd">    takes optional keyword arguments. The output is best described by example::</span>
+
+<span class="sd">        a()         -&gt; &#39;/a&#39;</span>
+<span class="sd">        b(x, y)     -&gt; &#39;/b/:x/:y&#39;</span>
+<span class="sd">        c(x, y=5)   -&gt; &#39;/c/:x&#39; and &#39;/c/:x/:y&#39;</span>
+<span class="sd">        d(x=5, y=6) -&gt; &#39;/d&#39; and &#39;/d/:x&#39; and &#39;/d/:x/:y&#39;</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+    <span class="kn">import</span> <span class="nn">inspect</span> <span class="c"># Expensive module. Only import if necessary.</span>
+    <span class="n">path</span> <span class="o">=</span> <span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="n">func</span><span class="o">.</span><span class="n">__name__</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;__&#39;</span><span class="p">,</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lstrip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+    <span class="n">spec</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
+    <span class="n">argc</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">spec</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">spec</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="ow">or</span> <span class="p">[])</span>
+    <span class="n">path</span> <span class="o">+=</span> <span class="p">(</span><span class="s">&#39;/:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">*</span> <span class="n">argc</span><span class="p">)</span> <span class="o">%</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">spec</span><span class="p">[</span><span class="mi">0</span><span class="p">][:</span><span class="n">argc</span><span class="p">])</span>
+    <span class="k">yield</span> <span class="n">path</span>
+    <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">spec</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">argc</span><span class="p">:]:</span>
+        <span class="n">path</span> <span class="o">+=</span> <span class="s">&#39;/:</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">arg</span>
+        <span class="k">yield</span> <span class="n">path</span>
+
+</div>
+<div class="viewcode-block" id="path_shift"><a class="viewcode-back" href="../api.html#bottle.path_shift">[docs]</a><span class="k">def</span> <span class="nf">path_shift</span><span class="p">(</span><span class="n">script_name</span><span class="p">,</span> <span class="n">path_info</span><span class="p">,</span> <span class="n">shift</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Shift path fragments from PATH_INFO to SCRIPT_NAME and vice versa.</span>
+
+<span class="sd">        :return: The modified paths.</span>
+<span class="sd">        :param script_name: The SCRIPT_NAME path.</span>
+<span class="sd">        :param script_name: The PATH_INFO path.</span>
+<span class="sd">        :param shift: The number of path fragments to shift. May be negative to</span>
+<span class="sd">          change the shift direction. (default: 1)</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+    <span class="k">if</span> <span class="n">shift</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="k">return</span> <span class="n">script_name</span><span class="p">,</span> <span class="n">path_info</span>
+    <span class="n">pathlist</span> <span class="o">=</span> <span class="n">path_info</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+    <span class="n">scriptlist</span> <span class="o">=</span> <span class="n">script_name</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">pathlist</span> <span class="ow">and</span> <span class="n">pathlist</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;&#39;</span><span class="p">:</span> <span class="n">pathlist</span> <span class="o">=</span> <span class="p">[]</span>
+    <span class="k">if</span> <span class="n">scriptlist</span> <span class="ow">and</span> <span class="n">scriptlist</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;&#39;</span><span class="p">:</span> <span class="n">scriptlist</span> <span class="o">=</span> <span class="p">[]</span>
+    <span class="k">if</span> <span class="n">shift</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">shift</span> <span class="o">&lt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">pathlist</span><span class="p">):</span>
+        <span class="n">moved</span> <span class="o">=</span> <span class="n">pathlist</span><span class="p">[:</span><span class="n">shift</span><span class="p">]</span>
+        <span class="n">scriptlist</span> <span class="o">=</span> <span class="n">scriptlist</span> <span class="o">+</span> <span class="n">moved</span>
+        <span class="n">pathlist</span> <span class="o">=</span> <span class="n">pathlist</span><span class="p">[</span><span class="n">shift</span><span class="p">:]</span>
+    <span class="k">elif</span> <span class="n">shift</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">shift</span> <span class="o">&gt;=</span> <span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="n">scriptlist</span><span class="p">):</span>
+        <span class="n">moved</span> <span class="o">=</span> <span class="n">scriptlist</span><span class="p">[</span><span class="n">shift</span><span class="p">:]</span>
+        <span class="n">pathlist</span> <span class="o">=</span> <span class="n">moved</span> <span class="o">+</span> <span class="n">pathlist</span>
+        <span class="n">scriptlist</span> <span class="o">=</span> <span class="n">scriptlist</span><span class="p">[:</span><span class="n">shift</span><span class="p">]</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">empty</span> <span class="o">=</span> <span class="s">&#39;SCRIPT_NAME&#39;</span> <span class="k">if</span> <span class="n">shift</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="k">else</span> <span class="s">&#39;PATH_INFO&#39;</span>
+        <span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="s">&quot;Cannot shift. Nothing left from </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">empty</span><span class="p">)</span>
+    <span class="n">new_script_name</span> <span class="o">=</span> <span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="s">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">scriptlist</span><span class="p">)</span>
+    <span class="n">new_path_info</span> <span class="o">=</span> <span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="s">&#39;/&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">pathlist</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">path_info</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">pathlist</span><span class="p">:</span> <span class="n">new_path_info</span> <span class="o">+=</span> <span class="s">&#39;/&#39;</span>
+    <span class="k">return</span> <span class="n">new_script_name</span><span class="p">,</span> <span class="n">new_path_info</span>
+
+</div>
+<span class="k">def</span> <span class="nf">validate</span><span class="p">(</span><span class="o">**</span><span class="n">vkargs</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot;</span>
+<span class="sd">    Validates and manipulates keyword arguments by user defined callables.</span>
+<span class="sd">    Handles ValueError and missing arguments by raising HTTPError(403).</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+    <span class="n">depr</span><span class="p">(</span><span class="s">&#39;Use route wildcard filters instead.&#39;</span><span class="p">)</span>
+    <span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
+        <span class="nd">@functools.wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kargs</span><span class="p">):</span>
+            <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">vkargs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+                <span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">kargs</span><span class="p">:</span>
+                    <span class="n">abort</span><span class="p">(</span><span class="mi">403</span><span class="p">,</span> <span class="s">&#39;Missing parameter: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">key</span><span class="p">)</span>
+                <span class="k">try</span><span class="p">:</span>
+                    <span class="n">kargs</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span><span class="p">(</span><span class="n">kargs</span><span class="p">[</span><span class="n">key</span><span class="p">])</span>
+                <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
+                    <span class="n">abort</span><span class="p">(</span><span class="mi">403</span><span class="p">,</span> <span class="s">&#39;Wrong parameter format for: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">key</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kargs</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+    <span class="k">return</span> <span class="n">decorator</span>
+
+
+<span class="k">def</span> <span class="nf">auth_basic</span><span class="p">(</span><span class="n">check</span><span class="p">,</span> <span class="n">realm</span><span class="o">=</span><span class="s">&quot;private&quot;</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s">&quot;Access denied&quot;</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Callback decorator to require HTTP auth (basic).</span>
+<span class="sd">        TODO: Add route(check_auth=...) parameter. &#39;&#39;&#39;</span>
+    <span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
+      <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+        <span class="n">user</span><span class="p">,</span> <span class="n">password</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">auth</span> <span class="ow">or</span> <span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">check</span><span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
+          <span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s">&#39;WWW-Authenticate&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;Basic realm=&quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="n">realm</span>
+          <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">401</span><span class="p">,</span> <span class="n">text</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+      <span class="k">return</span> <span class="n">wrapper</span>
+    <span class="k">return</span> <span class="n">decorator</span>
+
+
+<span class="c"># Shortcuts for common Bottle methods.</span>
+<span class="c"># They all refer to the current default application.</span>
+
+<span class="k">def</span> <span class="nf">make_default_app_wrapper</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Return a callable that relays calls to the current default app. &#39;&#39;&#39;</span>
+    <span class="nd">@functools.wraps</span><span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">Bottle</span><span class="p">,</span> <span class="n">name</span><span class="p">))</span>
+    <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">):</span>
+        <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">app</span><span class="p">(),</span> <span class="n">name</span><span class="p">)(</span><span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">**</span><span class="n">ka</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">wrapper</span>
+
+<span class="n">route</span>     <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;route&#39;</span><span class="p">)</span>
+<span class="n">get</span>       <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;get&#39;</span><span class="p">)</span>
+<span class="n">post</span>      <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;post&#39;</span><span class="p">)</span>
+<span class="n">put</span>       <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;put&#39;</span><span class="p">)</span>
+<span class="n">delete</span>    <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;delete&#39;</span><span class="p">)</span>
+<span class="n">error</span>     <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;error&#39;</span><span class="p">)</span>
+<span class="n">mount</span>     <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;mount&#39;</span><span class="p">)</span>
+<span class="n">hook</span>      <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;hook&#39;</span><span class="p">)</span>
+<span class="n">install</span>   <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;install&#39;</span><span class="p">)</span>
+<span class="n">uninstall</span> <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;uninstall&#39;</span><span class="p">)</span>
+<span class="n">url</span>       <span class="o">=</span> <span class="n">make_default_app_wrapper</span><span class="p">(</span><span class="s">&#39;get_url&#39;</span><span class="p">)</span>
+
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Server Adapter ###############################################################</span>
+<span class="c">###############################################################################</span>
+
+
+<span class="k">class</span> <span class="nc">ServerAdapter</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="n">quiet</span> <span class="o">=</span> <span class="bp">False</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span> <span class="o">**</span><span class="n">config</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="n">config</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">host</span> <span class="o">=</span> <span class="n">host</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">port</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="k">pass</span>
+
+    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">args</span> <span class="o">=</span> <span class="s">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">=</span><span class="si">%s</span><span class="s">&#39;</span><span class="o">%</span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="nb">repr</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span>
+        <span class="k">return</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">(</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">CGIServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="n">quiet</span> <span class="o">=</span> <span class="bp">True</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">from</span> <span class="nn">wsgiref.handlers</span> <span class="kn">import</span> <span class="n">CGIHandler</span>
+        <span class="k">def</span> <span class="nf">fixed_environ</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
+            <span class="n">environ</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">handler</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
+        <span class="n">CGIHandler</span><span class="p">()</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">fixed_environ</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">FlupFCGIServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">import</span> <span class="nn">flup.server.fcgi</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;bindAddress&#39;</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">))</span>
+        <span class="n">flup</span><span class="o">.</span><span class="n">server</span><span class="o">.</span><span class="n">fcgi</span><span class="o">.</span><span class="n">WSGIServer</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span> <span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">WSGIRefServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">from</span> <span class="nn">wsgiref.simple_server</span> <span class="kn">import</span> <span class="n">make_server</span><span class="p">,</span> <span class="n">WSGIRequestHandler</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">quiet</span><span class="p">:</span>
+            <span class="k">class</span> <span class="nc">QuietHandler</span><span class="p">(</span><span class="n">WSGIRequestHandler</span><span class="p">):</span>
+                <span class="k">def</span> <span class="nf">log_request</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span> <span class="k">pass</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="s">&#39;handler_class&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">QuietHandler</span>
+        <span class="n">srv</span> <span class="o">=</span> <span class="n">make_server</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">,</span> <span class="n">handler</span><span class="p">,</span> <span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">)</span>
+        <span class="n">srv</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">CherryPyServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">from</span> <span class="nn">cherrypy</span> <span class="kn">import</span> <span class="n">wsgiserver</span>
+        <span class="n">server</span> <span class="o">=</span> <span class="n">wsgiserver</span><span class="o">.</span><span class="n">CherryPyWSGIServer</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">),</span> <span class="n">handler</span><span class="p">)</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">server</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+        <span class="k">finally</span><span class="p">:</span>
+            <span class="n">server</span><span class="o">.</span><span class="n">stop</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">WaitressServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">waitress</span> <span class="kn">import</span> <span class="n">serve</span>
+        <span class="n">serve</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">PasteServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">from</span> <span class="nn">paste</span> <span class="kn">import</span> <span class="n">httpserver</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">quiet</span><span class="p">:</span>
+            <span class="kn">from</span> <span class="nn">paste.translogger</span> <span class="kn">import</span> <span class="n">TransLogger</span>
+            <span class="n">handler</span> <span class="o">=</span> <span class="n">TransLogger</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
+        <span class="n">httpserver</span><span class="o">.</span><span class="n">serve</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">),</span>
+                         <span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">MeinheldServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">meinheld</span> <span class="kn">import</span> <span class="n">server</span>
+        <span class="n">server</span><span class="o">.</span><span class="n">listen</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">))</span>
+        <span class="n">server</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">FapwsServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Extremely fast webserver using libev. See http://www.fapws.org/ &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">import</span> <span class="nn">fapws._evwsgi</span> <span class="kn">as</span> <span class="nn">evwsgi</span>
+        <span class="kn">from</span> <span class="nn">fapws</span> <span class="kn">import</span> <span class="n">base</span><span class="p">,</span> <span class="n">config</span>
+        <span class="n">port</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span>
+        <span class="k">if</span> <span class="nb">float</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">SERVER_IDENT</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">:])</span> <span class="o">&gt;</span> <span class="mf">0.4</span><span class="p">:</span>
+            <span class="c"># fapws3 silently changed its API in 0.5</span>
+            <span class="n">port</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">port</span><span class="p">)</span>
+        <span class="n">evwsgi</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
+        <span class="c"># fapws3 never releases the GIL. Complain upstream. I tried. No luck.</span>
+        <span class="k">if</span> <span class="s">&#39;BOTTLE_CHILD&#39;</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">quiet</span><span class="p">:</span>
+            <span class="n">_stderr</span><span class="p">(</span><span class="s">&quot;WARNING: Auto-reloading does not work with Fapws3.</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">)</span>
+            <span class="n">_stderr</span><span class="p">(</span><span class="s">&quot;         (Fapws3 breaks python thread support)</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">)</span>
+        <span class="n">evwsgi</span><span class="o">.</span><span class="n">set_base_module</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
+        <span class="k">def</span> <span class="nf">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
+            <span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.multiprocess&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="bp">False</span>
+            <span class="k">return</span> <span class="n">handler</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
+        <span class="n">evwsgi</span><span class="o">.</span><span class="n">wsgi_cb</span><span class="p">((</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="n">app</span><span class="p">))</span>
+        <span class="n">evwsgi</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">TornadoServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; The super hyped asynchronous server by facebook. Untested. &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span> <span class="c"># pragma: no cover</span>
+        <span class="kn">import</span> <span class="nn">tornado.wsgi</span><span class="o">,</span> <span class="nn">tornado.httpserver</span><span class="o">,</span> <span class="nn">tornado.ioloop</span>
+        <span class="n">container</span> <span class="o">=</span> <span class="n">tornado</span><span class="o">.</span><span class="n">wsgi</span><span class="o">.</span><span class="n">WSGIContainer</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
+        <span class="n">server</span> <span class="o">=</span> <span class="n">tornado</span><span class="o">.</span><span class="n">httpserver</span><span class="o">.</span><span class="n">HTTPServer</span><span class="p">(</span><span class="n">container</span><span class="p">)</span>
+        <span class="n">server</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="n">port</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
+        <span class="n">tornado</span><span class="o">.</span><span class="n">ioloop</span><span class="o">.</span><span class="n">IOLoop</span><span class="o">.</span><span class="n">instance</span><span class="p">()</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">AppEngineServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Adapter for Google App Engine. &quot;&quot;&quot;</span>
+    <span class="n">quiet</span> <span class="o">=</span> <span class="bp">True</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">google.appengine.ext.webapp</span> <span class="kn">import</span> <span class="n">util</span>
+        <span class="c"># A main() function in the handler script enables &#39;App Caching&#39;.</span>
+        <span class="c"># Lets makes sure it is there. This _really_ improves performance.</span>
+        <span class="n">module</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;__main__&#39;</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">module</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">&#39;main&#39;</span><span class="p">):</span>
+            <span class="n">module</span><span class="o">.</span><span class="n">main</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">util</span><span class="o">.</span><span class="n">run_wsgi_app</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
+        <span class="n">util</span><span class="o">.</span><span class="n">run_wsgi_app</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">TwistedServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested. &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">twisted.web</span> <span class="kn">import</span> <span class="n">server</span><span class="p">,</span> <span class="n">wsgi</span>
+        <span class="kn">from</span> <span class="nn">twisted.python.threadpool</span> <span class="kn">import</span> <span class="n">ThreadPool</span>
+        <span class="kn">from</span> <span class="nn">twisted.internet</span> <span class="kn">import</span> <span class="n">reactor</span>
+        <span class="n">thread_pool</span> <span class="o">=</span> <span class="n">ThreadPool</span><span class="p">()</span>
+        <span class="n">thread_pool</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+        <span class="n">reactor</span><span class="o">.</span><span class="n">addSystemEventTrigger</span><span class="p">(</span><span class="s">&#39;after&#39;</span><span class="p">,</span> <span class="s">&#39;shutdown&#39;</span><span class="p">,</span> <span class="n">thread_pool</span><span class="o">.</span><span class="n">stop</span><span class="p">)</span>
+        <span class="n">factory</span> <span class="o">=</span> <span class="n">server</span><span class="o">.</span><span class="n">Site</span><span class="p">(</span><span class="n">wsgi</span><span class="o">.</span><span class="n">WSGIResource</span><span class="p">(</span><span class="n">reactor</span><span class="p">,</span> <span class="n">thread_pool</span><span class="p">,</span> <span class="n">handler</span><span class="p">))</span>
+        <span class="n">reactor</span><span class="o">.</span><span class="n">listenTCP</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">,</span> <span class="n">factory</span><span class="p">,</span> <span class="n">interface</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">)</span>
+        <span class="n">reactor</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">DieselServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested. &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">diesel.protocols.wsgi</span> <span class="kn">import</span> <span class="n">WSGIApplication</span>
+        <span class="n">app</span> <span class="o">=</span> <span class="n">WSGIApplication</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
+        <span class="n">app</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">GeventServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested. Options:</span>
+
+<span class="sd">        * `fast` (default: False) uses libevent&#39;s http server, but has some</span>
+<span class="sd">          issues: No streaming, no pipelining, no SSL.</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">gevent</span> <span class="kn">import</span> <span class="n">wsgi</span><span class="p">,</span> <span class="n">pywsgi</span><span class="p">,</span> <span class="n">local</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">_lctx</span><span class="p">,</span> <span class="n">local</span><span class="o">.</span><span class="n">local</span><span class="p">):</span>
+            <span class="n">msg</span> <span class="o">=</span> <span class="s">&quot;Bottle requires gevent.monkey.patch_all() (before import)&quot;</span>
+            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;fast&#39;</span><span class="p">):</span> <span class="n">wsgi</span> <span class="o">=</span> <span class="n">pywsgi</span>
+        <span class="n">log</span> <span class="o">=</span> <span class="bp">None</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">quiet</span> <span class="k">else</span> <span class="s">&#39;default&#39;</span>
+        <span class="n">wsgi</span><span class="o">.</span><span class="n">WSGIServer</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">),</span> <span class="n">handler</span><span class="p">,</span> <span class="n">log</span><span class="o">=</span><span class="n">log</span><span class="p">)</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">GunicornServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested. See http://gunicorn.org/configure.html for options. &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">gunicorn.app.base</span> <span class="kn">import</span> <span class="n">Application</span>
+
+        <span class="n">config</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;bind&#39;</span><span class="p">:</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">:</span><span class="si">%d</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">))}</span>
+        <span class="n">config</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">)</span>
+
+        <span class="k">class</span> <span class="nc">GunicornApplication</span><span class="p">(</span><span class="n">Application</span><span class="p">):</span>
+            <span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parser</span><span class="p">,</span> <span class="n">opts</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
+                <span class="k">return</span> <span class="n">config</span>
+
+            <span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+                <span class="k">return</span> <span class="n">handler</span>
+
+        <span class="n">GunicornApplication</span><span class="p">()</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">EventletServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">eventlet</span> <span class="kn">import</span> <span class="n">wsgi</span><span class="p">,</span> <span class="n">listen</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">listen</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">)),</span> <span class="n">handler</span><span class="p">,</span>
+                        <span class="n">log_output</span><span class="o">=</span><span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">quiet</span><span class="p">))</span>
+        <span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
+            <span class="c"># Fallback, if we have old version of eventlet</span>
+            <span class="n">wsgi</span><span class="o">.</span><span class="n">server</span><span class="p">(</span><span class="n">listen</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">)),</span> <span class="n">handler</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">RocketServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested. &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">rocket</span> <span class="kn">import</span> <span class="n">Rocket</span>
+        <span class="n">server</span> <span class="o">=</span> <span class="n">Rocket</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">),</span> <span class="s">&#39;wsgi&#39;</span><span class="p">,</span> <span class="p">{</span> <span class="s">&#39;wsgi_app&#39;</span> <span class="p">:</span> <span class="n">handler</span> <span class="p">})</span>
+        <span class="n">server</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+
+<span class="k">class</span> <span class="nc">BjoernServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Fast server written in C: https://github.com/jonashaag/bjoern &quot;&quot;&quot;</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">bjoern</span> <span class="kn">import</span> <span class="n">run</span>
+        <span class="n">run</span><span class="p">(</span><span class="n">handler</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">AutoServer</span><span class="p">(</span><span class="n">ServerAdapter</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Untested. &quot;&quot;&quot;</span>
+    <span class="n">adapters</span> <span class="o">=</span> <span class="p">[</span><span class="n">WaitressServer</span><span class="p">,</span> <span class="n">PasteServer</span><span class="p">,</span> <span class="n">TwistedServer</span><span class="p">,</span> <span class="n">CherryPyServer</span><span class="p">,</span> <span class="n">WSGIRefServer</span><span class="p">]</span>
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">sa</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">adapters</span><span class="p">:</span>
+            <span class="k">try</span><span class="p">:</span>
+                <span class="k">return</span> <span class="n">sa</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">port</span><span class="p">,</span> <span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
+            <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
+                <span class="k">pass</span>
+
+<span class="n">server_names</span> <span class="o">=</span> <span class="p">{</span>
+    <span class="s">&#39;cgi&#39;</span><span class="p">:</span> <span class="n">CGIServer</span><span class="p">,</span>
+    <span class="s">&#39;flup&#39;</span><span class="p">:</span> <span class="n">FlupFCGIServer</span><span class="p">,</span>
+    <span class="s">&#39;wsgiref&#39;</span><span class="p">:</span> <span class="n">WSGIRefServer</span><span class="p">,</span>
+    <span class="s">&#39;waitress&#39;</span><span class="p">:</span> <span class="n">WaitressServer</span><span class="p">,</span>
+    <span class="s">&#39;cherrypy&#39;</span><span class="p">:</span> <span class="n">CherryPyServer</span><span class="p">,</span>
+    <span class="s">&#39;paste&#39;</span><span class="p">:</span> <span class="n">PasteServer</span><span class="p">,</span>
+    <span class="s">&#39;fapws3&#39;</span><span class="p">:</span> <span class="n">FapwsServer</span><span class="p">,</span>
+    <span class="s">&#39;tornado&#39;</span><span class="p">:</span> <span class="n">TornadoServer</span><span class="p">,</span>
+    <span class="s">&#39;gae&#39;</span><span class="p">:</span> <span class="n">AppEngineServer</span><span class="p">,</span>
+    <span class="s">&#39;twisted&#39;</span><span class="p">:</span> <span class="n">TwistedServer</span><span class="p">,</span>
+    <span class="s">&#39;diesel&#39;</span><span class="p">:</span> <span class="n">DieselServer</span><span class="p">,</span>
+    <span class="s">&#39;meinheld&#39;</span><span class="p">:</span> <span class="n">MeinheldServer</span><span class="p">,</span>
+    <span class="s">&#39;gunicorn&#39;</span><span class="p">:</span> <span class="n">GunicornServer</span><span class="p">,</span>
+    <span class="s">&#39;eventlet&#39;</span><span class="p">:</span> <span class="n">EventletServer</span><span class="p">,</span>
+    <span class="s">&#39;gevent&#39;</span><span class="p">:</span> <span class="n">GeventServer</span><span class="p">,</span>
+    <span class="s">&#39;rocket&#39;</span><span class="p">:</span> <span class="n">RocketServer</span><span class="p">,</span>
+    <span class="s">&#39;bjoern&#39;</span> <span class="p">:</span> <span class="n">BjoernServer</span><span class="p">,</span>
+    <span class="s">&#39;auto&#39;</span><span class="p">:</span> <span class="n">AutoServer</span><span class="p">,</span>
+<span class="p">}</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Application Control ##########################################################</span>
+<span class="c">###############################################################################</span>
+
+
+<div class="viewcode-block" id="load"><a class="viewcode-back" href="../api.html#bottle.load">[docs]</a><span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="o">**</span><span class="n">namespace</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Import a module or fetch an object from a module.</span>
+
+<span class="sd">        * ``package.module`` returns `module` as a module object.</span>
+<span class="sd">        * ``pack.mod:name`` returns the module variable `name` from `pack.mod`.</span>
+<span class="sd">        * ``pack.mod:func()`` calls `pack.mod.func()` and returns the result.</span>
+
+<span class="sd">        The last form accepts not only function calls, but any type of</span>
+<span class="sd">        expression. Keyword arguments passed to this function are available as</span>
+<span class="sd">        local variables. Example: ``import_string(&#39;re:compile(x)&#39;, x=&#39;[a-z]&#39;)``</span>
+<span class="sd">    &quot;&quot;&quot;</span>
+    <span class="n">module</span><span class="p">,</span> <span class="n">target</span> <span class="o">=</span> <span class="n">target</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;:&quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="s">&#39;:&#39;</span> <span class="ow">in</span> <span class="n">target</span> <span class="k">else</span> <span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">module</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">:</span> <span class="nb">__import__</span><span class="p">(</span><span class="n">module</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">target</span><span class="p">:</span> <span class="k">return</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">module</span><span class="p">]</span>
+    <span class="k">if</span> <span class="n">target</span><span class="o">.</span><span class="n">isalnum</span><span class="p">():</span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">module</span><span class="p">],</span> <span class="n">target</span><span class="p">)</span>
+    <span class="n">package_name</span> <span class="o">=</span> <span class="n">module</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
+    <span class="n">namespace</span><span class="p">[</span><span class="n">package_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="n">package_name</span><span class="p">]</span>
+    <span class="k">return</span> <span class="nb">eval</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">.</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="n">target</span><span class="p">),</span> <span class="n">namespace</span><span class="p">)</span>
+
+</div>
+<div class="viewcode-block" id="load_app"><a class="viewcode-back" href="../api.html#bottle.load_app">[docs]</a><span class="k">def</span> <span class="nf">load_app</span><span class="p">(</span><span class="n">target</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Load a bottle application from a module and make sure that the import</span>
+<span class="sd">        does not affect the current default application, but returns a separate</span>
+<span class="sd">        application object. See :func:`load` for the target parameter. &quot;&quot;&quot;</span>
+    <span class="k">global</span> <span class="n">NORUN</span><span class="p">;</span> <span class="n">NORUN</span><span class="p">,</span> <span class="n">nr_old</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span> <span class="n">NORUN</span>
+    <span class="k">try</span><span class="p">:</span>
+        <span class="n">tmp</span> <span class="o">=</span> <span class="n">default_app</span><span class="o">.</span><span class="n">push</span><span class="p">()</span> <span class="c"># Create a new &quot;default application&quot;</span>
+        <span class="n">rv</span> <span class="o">=</span> <span class="n">load</span><span class="p">(</span><span class="n">target</span><span class="p">)</span> <span class="c"># Import the target module</span>
+        <span class="k">return</span> <span class="n">rv</span> <span class="k">if</span> <span class="nb">callable</span><span class="p">(</span><span class="n">rv</span><span class="p">)</span> <span class="k">else</span> <span class="n">tmp</span>
+    <span class="k">finally</span><span class="p">:</span>
+        <span class="n">default_app</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">tmp</span><span class="p">)</span> <span class="c"># Remove the temporary added default application</span>
+        <span class="n">NORUN</span> <span class="o">=</span> <span class="n">nr_old</span>
+</div>
+<span class="n">_debug</span> <span class="o">=</span> <span class="n">debug</span>
+<div class="viewcode-block" id="run"><a class="viewcode-back" href="../api.html#bottle.run">[docs]</a><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">server</span><span class="o">=</span><span class="s">&#39;wsgiref&#39;</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="s">&#39;127.0.0.1&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span>
+        <span class="n">interval</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">reloader</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">quiet</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">plugins</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span>
+        <span class="n">debug</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kargs</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Start a server instance. This method blocks until the server terminates.</span>
+
+<span class="sd">        :param app: WSGI application or target string supported by</span>
+<span class="sd">               :func:`load_app`. (default: :func:`default_app`)</span>
+<span class="sd">        :param server: Server adapter to use. See :data:`server_names` keys</span>
+<span class="sd">               for valid names or pass a :class:`ServerAdapter` subclass.</span>
+<span class="sd">               (default: `wsgiref`)</span>
+<span class="sd">        :param host: Server address to bind to. Pass ``0.0.0.0`` to listens on</span>
+<span class="sd">               all interfaces including the external one. (default: 127.0.0.1)</span>
+<span class="sd">        :param port: Server port to bind to. Values below 1024 require root</span>
+<span class="sd">               privileges. (default: 8080)</span>
+<span class="sd">        :param reloader: Start auto-reloading server? (default: False)</span>
+<span class="sd">        :param interval: Auto-reloader interval in seconds (default: 1)</span>
+<span class="sd">        :param quiet: Suppress output to stdout and stderr? (default: False)</span>
+<span class="sd">        :param options: Options passed to the server adapter.</span>
+<span class="sd">     &quot;&quot;&quot;</span>
+    <span class="k">if</span> <span class="n">NORUN</span><span class="p">:</span> <span class="k">return</span>
+    <span class="k">if</span> <span class="n">reloader</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;BOTTLE_CHILD&#39;</span><span class="p">):</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">lockfile</span> <span class="o">=</span> <span class="bp">None</span>
+            <span class="n">fd</span><span class="p">,</span> <span class="n">lockfile</span> <span class="o">=</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s">&#39;bottle.&#39;</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s">&#39;.lock&#39;</span><span class="p">)</span>
+            <span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span> <span class="c"># We only need this file to exist. We never write to it</span>
+            <span class="k">while</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lockfile</span><span class="p">):</span>
+                <span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">sys</span><span class="o">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span>
+                <span class="n">environ</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
+                <span class="n">environ</span><span class="p">[</span><span class="s">&#39;BOTTLE_CHILD&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;true&#39;</span>
+                <span class="n">environ</span><span class="p">[</span><span class="s">&#39;BOTTLE_LOCKFILE&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">lockfile</span>
+                <span class="n">p</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="n">environ</span><span class="p">)</span>
+                <span class="k">while</span> <span class="n">p</span><span class="o">.</span><span class="n">poll</span><span class="p">()</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="c"># Busy wait...</span>
+                    <span class="n">os</span><span class="o">.</span><span class="n">utime</span><span class="p">(</span><span class="n">lockfile</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="c"># I am alive!</span>
+                    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">p</span><span class="o">.</span><span class="n">poll</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
+                    <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lockfile</span><span class="p">):</span> <span class="n">os</span><span class="o">.</span><span class="n">unlink</span><span class="p">(</span><span class="n">lockfile</span><span class="p">)</span>
+                    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">poll</span><span class="p">())</span>
+        <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
+            <span class="k">pass</span>
+        <span class="k">finally</span><span class="p">:</span>
+            <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lockfile</span><span class="p">):</span>
+                <span class="n">os</span><span class="o">.</span><span class="n">unlink</span><span class="p">(</span><span class="n">lockfile</span><span class="p">)</span>
+        <span class="k">return</span>
+
+    <span class="k">try</span><span class="p">:</span>
+        <span class="n">_debug</span><span class="p">(</span><span class="n">debug</span><span class="p">)</span>
+        <span class="n">app</span> <span class="o">=</span> <span class="n">app</span> <span class="ow">or</span> <span class="n">default_app</span><span class="p">()</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
+            <span class="n">app</span> <span class="o">=</span> <span class="n">load_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="nb">callable</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Application is not callable: </span><span class="si">%r</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">app</span><span class="p">)</span>
+
+        <span class="k">for</span> <span class="n">plugin</span> <span class="ow">in</span> <span class="n">plugins</span> <span class="ow">or</span> <span class="p">[]:</span>
+            <span class="n">app</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">plugin</span><span class="p">)</span>
+
+        <span class="k">if</span> <span class="n">server</span> <span class="ow">in</span> <span class="n">server_names</span><span class="p">:</span>
+            <span class="n">server</span> <span class="o">=</span> <span class="n">server_names</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">server</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
+            <span class="n">server</span> <span class="o">=</span> <span class="n">load</span><span class="p">(</span><span class="n">server</span><span class="p">)</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="nb">type</span><span class="p">):</span>
+            <span class="n">server</span> <span class="o">=</span> <span class="n">server</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="o">**</span><span class="n">kargs</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="n">ServerAdapter</span><span class="p">):</span>
+            <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Unknown or unsupported server: </span><span class="si">%r</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">server</span><span class="p">)</span>
+
+        <span class="n">server</span><span class="o">.</span><span class="n">quiet</span> <span class="o">=</span> <span class="n">server</span><span class="o">.</span><span class="n">quiet</span> <span class="ow">or</span> <span class="n">quiet</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">server</span><span class="o">.</span><span class="n">quiet</span><span class="p">:</span>
+            <span class="n">_stderr</span><span class="p">(</span><span class="s">&quot;Bottle v</span><span class="si">%s</span><span class="s"> server starting up (using </span><span class="si">%s</span><span class="s">)...</span><span class="se">\n</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">__version__</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">server</span><span class="p">)))</span>
+            <span class="n">_stderr</span><span class="p">(</span><span class="s">&quot;Listening on http://</span><span class="si">%s</span><span class="s">:</span><span class="si">%d</span><span class="s">/</span><span class="se">\n</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">server</span><span class="o">.</span><span class="n">host</span><span class="p">,</span> <span class="n">server</span><span class="o">.</span><span class="n">port</span><span class="p">))</span>
+            <span class="n">_stderr</span><span class="p">(</span><span class="s">&quot;Hit Ctrl-C to quit.</span><span class="se">\n\n</span><span class="s">&quot;</span><span class="p">)</span>
+
+        <span class="k">if</span> <span class="n">reloader</span><span class="p">:</span>
+            <span class="n">lockfile</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;BOTTLE_LOCKFILE&#39;</span><span class="p">)</span>
+            <span class="n">bgcheck</span> <span class="o">=</span> <span class="n">FileCheckerThread</span><span class="p">(</span><span class="n">lockfile</span><span class="p">,</span> <span class="n">interval</span><span class="p">)</span>
+            <span class="k">with</span> <span class="n">bgcheck</span><span class="p">:</span>
+                <span class="n">server</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">bgcheck</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s">&#39;reload&#39;</span><span class="p">:</span>
+                <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">server</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+    <span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
+        <span class="k">pass</span>
+    <span class="k">except</span> <span class="p">(</span><span class="ne">SystemExit</span><span class="p">,</span> <span class="ne">MemoryError</span><span class="p">):</span>
+        <span class="k">raise</span>
+    <span class="k">except</span><span class="p">:</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">reloader</span><span class="p">:</span> <span class="k">raise</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">server</span><span class="p">,</span> <span class="s">&#39;quiet&#39;</span><span class="p">,</span> <span class="n">quiet</span><span class="p">):</span>
+            <span class="n">print_exc</span><span class="p">()</span>
+        <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
+        <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
+
+
+</div>
+<span class="k">class</span> <span class="nc">FileCheckerThread</span><span class="p">(</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Interrupt main-thread as soon as a changed module file is detected,</span>
+<span class="sd">        the lockfile gets deleted or gets to old. &#39;&#39;&#39;</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lockfile</span><span class="p">,</span> <span class="n">interval</span><span class="p">):</span>
+        <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">lockfile</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">=</span> <span class="n">lockfile</span><span class="p">,</span> <span class="n">interval</span>
+        <span class="c">#: Is one of &#39;reload&#39;, &#39;error&#39; or &#39;exit&#39;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="bp">None</span>
+
+    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">exists</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span>
+        <span class="n">mtime</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">path</span><span class="p">:</span> <span class="n">os</span><span class="o">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">)</span><span class="o">.</span><span class="n">st_mtime</span>
+        <span class="n">files</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
+
+        <span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">values</span><span class="p">()):</span>
+            <span class="n">path</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">&#39;__file__&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">path</span><span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">:]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;.pyo&#39;</span><span class="p">,</span> <span class="s">&#39;.pyc&#39;</span><span class="p">):</span> <span class="n">path</span> <span class="o">=</span> <span class="n">path</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
+            <span class="k">if</span> <span class="n">path</span> <span class="ow">and</span> <span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span> <span class="n">files</span><span class="p">[</span><span class="n">path</span><span class="p">]</span> <span class="o">=</span> <span class="n">mtime</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
+
+        <span class="k">while</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">exists</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lockfile</span><span class="p">)</span>\
+            <span class="ow">or</span> <span class="n">mtime</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">lockfile</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">interval</span> <span class="o">-</span> <span class="mi">5</span><span class="p">:</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">&#39;error&#39;</span>
+                <span class="n">thread</span><span class="o">.</span><span class="n">interrupt_main</span><span class="p">()</span>
+            <span class="k">for</span> <span class="n">path</span><span class="p">,</span> <span class="n">lmtime</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">files</span><span class="o">.</span><span class="n">items</span><span class="p">()):</span>
+                <span class="k">if</span> <span class="ow">not</span> <span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="ow">or</span> <span class="n">mtime</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">lmtime</span><span class="p">:</span>
+                    <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">&#39;reload&#39;</span>
+                    <span class="n">thread</span><span class="o">.</span><span class="n">interrupt_main</span><span class="p">()</span>
+                    <span class="k">break</span>
+            <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">interval</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
+
+    <span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_val</span><span class="p">,</span> <span class="n">exc_tb</span><span class="p">):</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">&#39;exit&#39;</span> <span class="c"># silent exit</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
+        <span class="k">return</span> <span class="n">exc_type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">exc_type</span><span class="p">,</span> <span class="ne">KeyboardInterrupt</span><span class="p">)</span>
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Template Adapters ############################################################</span>
+<span class="c">###############################################################################</span>
+
+
+<span class="k">class</span> <span class="nc">TemplateError</span><span class="p">(</span><span class="n">HTTPError</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
+        <span class="n">HTTPError</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="mi">500</span><span class="p">,</span> <span class="n">message</span><span class="p">)</span>
+
+
+<div class="viewcode-block" id="BaseTemplate"><a class="viewcode-back" href="../api.html#bottle.BaseTemplate">[docs]</a><span class="k">class</span> <span class="nc">BaseTemplate</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&quot;&quot;&quot; Base class and minimal API for template adapters &quot;&quot;&quot;</span>
+    <span class="n">extensions</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;tpl&#39;</span><span class="p">,</span><span class="s">&#39;html&#39;</span><span class="p">,</span><span class="s">&#39;thtml&#39;</span><span class="p">,</span><span class="s">&#39;stpl&#39;</span><span class="p">]</span>
+    <span class="n">settings</span> <span class="o">=</span> <span class="p">{}</span> <span class="c">#used in prepare()</span>
+    <span class="n">defaults</span> <span class="o">=</span> <span class="p">{}</span> <span class="c">#used in render()</span>
+
+<div class="viewcode-block" id="BaseTemplate.__init__"><a class="viewcode-back" href="../api.html#bottle.BaseTemplate.__init__">[docs]</a>    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="p">[],</span> <span class="n">encoding</span><span class="o">=</span><span class="s">&#39;utf8&#39;</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Create a new template.</span>
+<span class="sd">        If the source parameter (str or buffer) is missing, the name argument</span>
+<span class="sd">        is used to guess a template filename. Subclasses can assume that</span>
+<span class="sd">        self.source and/or self.filename are set. Both are strings.</span>
+<span class="sd">        The lookup, encoding and settings parameters are stored as instance</span>
+<span class="sd">        variables.</span>
+<span class="sd">        The lookup parameter stores a list containing directory paths.</span>
+<span class="sd">        The encoding parameter should be used to decode byte strings or files.</span>
+<span class="sd">        The settings parameter contains a dict for engine-specific settings.</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">source</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="s">&#39;read&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="n">source</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">filename</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">source</span><span class="p">,</span> <span class="s">&#39;filename&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="bp">None</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">lookup</span> <span class="o">=</span> <span class="p">[</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">lookup</span><span class="p">]</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">encoding</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">settings</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="c"># Copy from class variable</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">settings</span><span class="p">)</span> <span class="c"># Apply</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">filename</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookup</span><span class="p">)</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
+                <span class="k">raise</span> <span class="n">TemplateError</span><span class="p">(</span><span class="s">&#39;Template </span><span class="si">%s</span><span class="s"> not found.&#39;</span> <span class="o">%</span> <span class="nb">repr</span><span class="p">(</span><span class="n">name</span><span class="p">))</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">:</span>
+            <span class="k">raise</span> <span class="n">TemplateError</span><span class="p">(</span><span class="s">&#39;No template specified.&#39;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="o">**</span><span class="bp">self</span><span class="o">.</span><span class="n">settings</span><span class="p">)</span>
+</div>
+    <span class="nd">@classmethod</span>
+<div class="viewcode-block" id="BaseTemplate.search"><a class="viewcode-back" href="../api.html#bottle.BaseTemplate.search">[docs]</a>    <span class="k">def</span> <span class="nf">search</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="p">[]):</span>
+        <span class="sd">&quot;&quot;&quot; Search name in all directories specified in lookup.</span>
+<span class="sd">        First without, then with common extensions. Return first hit. &quot;&quot;&quot;</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">lookup</span><span class="p">:</span>
+            <span class="n">depr</span><span class="p">(</span><span class="s">&#39;The template lookup path list should not be empty.&#39;</span><span class="p">)</span>
+            <span class="n">lookup</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;.&#39;</span><span class="p">]</span>
+
+        <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isabs</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
+            <span class="n">depr</span><span class="p">(</span><span class="s">&#39;Absolute template path names are deprecated.&#39;</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
+
+        <span class="k">for</span> <span class="n">spath</span> <span class="ow">in</span> <span class="n">lookup</span><span class="p">:</span>
+            <span class="n">spath</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">spath</span><span class="p">)</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">sep</span>
+            <span class="n">fname</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">spath</span><span class="p">,</span> <span class="n">name</span><span class="p">))</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">fname</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">spath</span><span class="p">):</span> <span class="k">continue</span>
+            <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">fname</span><span class="p">):</span> <span class="k">return</span> <span class="n">fname</span>
+            <span class="k">for</span> <span class="n">ext</span> <span class="ow">in</span> <span class="n">cls</span><span class="o">.</span><span class="n">extensions</span><span class="p">:</span>
+                <span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isfile</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s">.</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="n">ext</span><span class="p">)):</span>
+                    <span class="k">return</span> <span class="s">&#39;</span><span class="si">%s</span><span class="s">.</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="n">ext</span><span class="p">)</span>
+</div>
+    <span class="nd">@classmethod</span>
+<div class="viewcode-block" id="BaseTemplate.global_config"><a class="viewcode-back" href="../api.html#bottle.BaseTemplate.global_config">[docs]</a>    <span class="k">def</span> <span class="nf">global_config</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; This reads or sets the global settings stored in class.settings. &#39;&#39;&#39;</span>
+        <span class="k">if</span> <span class="n">args</span><span class="p">:</span>
+            <span class="n">cls</span><span class="o">.</span><span class="n">settings</span> <span class="o">=</span> <span class="n">cls</span><span class="o">.</span><span class="n">settings</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="c"># Make settings local to class</span>
+            <span class="n">cls</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">cls</span><span class="o">.</span><span class="n">settings</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
+</div>
+<div class="viewcode-block" id="BaseTemplate.prepare"><a class="viewcode-back" href="../api.html#bottle.BaseTemplate.prepare">[docs]</a>    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Run preparations (parsing, caching, ...).</span>
+<span class="sd">        It should be possible to call this again to refresh a template or to</span>
+<span class="sd">        update settings.</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="k">raise</span> <span class="ne">NotImplementedError</span>
+</div>
+<div class="viewcode-block" id="BaseTemplate.render"><a class="viewcode-back" href="../api.html#bottle.BaseTemplate.render">[docs]</a>    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Render the template with the specified local variables and return</span>
+<span class="sd">        a single byte or unicode string. If it is a byte string, the encoding</span>
+<span class="sd">        must match self.encoding. This method must be thread-safe!</span>
+<span class="sd">        Local variables may be provided in dictionaries (*args)</span>
+<span class="sd">        or directly, as keywords (**kwargs).</span>
+<span class="sd">        &quot;&quot;&quot;</span>
+        <span class="k">raise</span> <span class="ne">NotImplementedError</span>
+
+</div></div>
+<span class="k">class</span> <span class="nc">MakoTemplate</span><span class="p">(</span><span class="n">BaseTemplate</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">mako.template</span> <span class="kn">import</span> <span class="n">Template</span>
+        <span class="kn">from</span> <span class="nn">mako.lookup</span> <span class="kn">import</span> <span class="n">TemplateLookup</span>
+        <span class="n">options</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s">&#39;input_encoding&#39;</span><span class="p">:</span><span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">})</span>
+        <span class="n">options</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;format_exceptions&#39;</span><span class="p">,</span> <span class="nb">bool</span><span class="p">(</span><span class="n">DEBUG</span><span class="p">))</span>
+        <span class="n">lookup</span> <span class="o">=</span> <span class="n">TemplateLookup</span><span class="p">(</span><span class="n">directories</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">lookup</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="n">lookup</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="n">uri</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="n">lookup</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="n">_defaults</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
+        <span class="n">_defaults</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="o">**</span><span class="n">_defaults</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">CheetahTemplate</span><span class="p">(</span><span class="n">BaseTemplate</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">Cheetah.Template</span> <span class="kn">import</span> <span class="n">Template</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">local</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">vars</span> <span class="o">=</span> <span class="p">{}</span>
+        <span class="n">options</span><span class="p">[</span><span class="s">&#39;searchList&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">vars</span><span class="p">]</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="n">source</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">vars</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">vars</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
+        <span class="n">out</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tpl</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">context</span><span class="o">.</span><span class="n">vars</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
+        <span class="k">return</span> <span class="n">out</span>
+
+
+<span class="k">class</span> <span class="nc">Jinja2Template</span><span class="p">(</span><span class="n">BaseTemplate</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">filters</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">tests</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">jinja2</span> <span class="kn">import</span> <span class="n">Environment</span><span class="p">,</span> <span class="n">FunctionLoader</span>
+        <span class="k">if</span> <span class="s">&#39;prefix&#39;</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span> <span class="c"># TODO: to be removed after a while</span>
+            <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&#39;The keyword argument `prefix` has been removed. &#39;</span>
+                <span class="s">&#39;Use the full jinja2 environment name line_statement_prefix instead.&#39;</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">Environment</span><span class="p">(</span><span class="n">loader</span><span class="o">=</span><span class="n">FunctionLoader</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">loader</span><span class="p">),</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">filters</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">filters</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">filters</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">tests</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">tests</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">tests</span><span class="p">)</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">from_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">get_template</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="n">_defaults</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
+        <span class="n">_defaults</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="o">**</span><span class="n">_defaults</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">loader</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
+        <span class="n">fname</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">lookup</span><span class="p">)</span>
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">fname</span><span class="p">:</span> <span class="k">return</span>
+        <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="s">&quot;rb&quot;</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">)</span>
+
+
+<span class="k">class</span> <span class="nc">SimpleTALTemplate</span><span class="p">(</span><span class="n">BaseTemplate</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Deprecated, do not use. &#39;&#39;&#39;</span>
+    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
+        <span class="n">depr</span><span class="p">(</span><span class="s">&#39;The SimpleTAL template handler is deprecated&#39;</span>\
+             <span class="s">&#39; and will be removed in 0.12&#39;</span><span class="p">)</span>
+        <span class="kn">from</span> <span class="nn">simpletal</span> <span class="kn">import</span> <span class="n">simpleTAL</span>
+        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="n">simpleTAL</span><span class="o">.</span><span class="n">compileHTMLTemplate</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">source</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
+                <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span> <span class="o">=</span> <span class="n">simpleTAL</span><span class="o">.</span><span class="n">compileHTMLTemplate</span><span class="p">(</span><span class="n">tonat</span><span class="p">(</span><span class="n">fp</span><span class="o">.</span><span class="n">read</span><span class="p">()))</span>
+
+    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="kn">from</span> <span class="nn">simpletal</span> <span class="kn">import</span> <span class="n">simpleTALES</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="n">context</span> <span class="o">=</span> <span class="n">simpleTALES</span><span class="o">.</span><span class="n">Context</span><span class="p">()</span>
+        <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+            <span class="n">context</span><span class="o">.</span><span class="n">addGlobal</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
+        <span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
+            <span class="n">context</span><span class="o">.</span><span class="n">addGlobal</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
+        <span class="n">output</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">tpl</span><span class="o">.</span><span class="n">expand</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">output</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">output</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span>
+
+
+<div class="viewcode-block" id="SimpleTemplate"><a class="viewcode-back" href="../stpl.html#bottle.SimpleTemplate">[docs]</a><span class="k">class</span> <span class="nc">SimpleTemplate</span><span class="p">(</span><span class="n">BaseTemplate</span><span class="p">):</span>
+    <span class="n">blocks</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;if&#39;</span><span class="p">,</span> <span class="s">&#39;elif&#39;</span><span class="p">,</span> <span class="s">&#39;else&#39;</span><span class="p">,</span> <span class="s">&#39;try&#39;</span><span class="p">,</span> <span class="s">&#39;except&#39;</span><span class="p">,</span> <span class="s">&#39;finally&#39;</span><span class="p">,</span> <span class="s">&#39;for&#39;</span><span class="p">,</span> <span class="s">&#39;while&#39;</span><span class="p">,</span>
+              <span class="s">&#39;with&#39;</span><span class="p">,</span> <span class="s">&#39;def&#39;</span><span class="p">,</span> <span class="s">&#39;class&#39;</span><span class="p">)</span>
+    <span class="n">dedent_blocks</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;elif&#39;</span><span class="p">,</span> <span class="s">&#39;else&#39;</span><span class="p">,</span> <span class="s">&#39;except&#39;</span><span class="p">,</span> <span class="s">&#39;finally&#39;</span><span class="p">)</span>
+
+    <span class="nd">@lazy_attribute</span>
+    <span class="k">def</span> <span class="nf">re_pytokens</span><span class="p">(</span><span class="n">cls</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; This matches comments and all kinds of quoted strings but does</span>
+<span class="sd">            NOT match comments (#...) within quoted strings. (trust me) &#39;&#39;&#39;</span>
+        <span class="k">return</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">r&#39;&#39;&#39;</span>
+<span class="s">            (&#39;&#39;(?!&#39;)|&quot;&quot;(?!&quot;)|&#39;{6}|&quot;{6}    # Empty strings (all 4 types)</span>
+<span class="s">             |&#39;(?:[^\\&#39;]|\\.)+?&#39;          # Single quotes (&#39;)</span>
+<span class="s">             |&quot;(?:[^\\&quot;]|\\.)+?&quot;          # Double quotes (&quot;)</span>
+<span class="s">             |&#39;{3}(?:[^\\]|\\.|\n)+?&#39;{3}  # Triple-quoted strings (&#39;)</span>
+<span class="s">             |&quot;{3}(?:[^\\]|\\.|\n)+?&quot;{3}  # Triple-quoted strings (&quot;)</span>
+<span class="s">             |\#.*                        # Comments</span>
+<span class="s">            )&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">VERBOSE</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">prepare</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">escape_func</span><span class="o">=</span><span class="n">html_escape</span><span class="p">,</span> <span class="n">noescape</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="p">{}</span>
+        <span class="n">enc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_str</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">touni</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">enc</span><span class="p">)</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">_escape</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">escape_func</span><span class="p">(</span><span class="n">touni</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">enc</span><span class="p">))</span>
+        <span class="k">if</span> <span class="n">noescape</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">_str</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_escape</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_escape</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_str</span>
+
+    <span class="nd">@classmethod</span>
+<div class="viewcode-block" id="SimpleTemplate.split_comment"><a class="viewcode-back" href="../stpl.html#bottle.SimpleTemplate.split_comment">[docs]</a>    <span class="k">def</span> <span class="nf">split_comment</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">code</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Removes comments (#...) from python code. &quot;&quot;&quot;</span>
+        <span class="k">if</span> <span class="s">&#39;#&#39;</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">code</span><span class="p">:</span> <span class="k">return</span> <span class="n">code</span>
+        <span class="c">#: Remove comments only (leave quoted strings as they are)</span>
+        <span class="n">subf</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">m</span><span class="p">:</span> <span class="s">&#39;&#39;</span> <span class="k">if</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">==</span><span class="s">&#39;#&#39;</span> <span class="k">else</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">re</span><span class="o">.</span><span class="n">sub</span><span class="p">(</span><span class="n">cls</span><span class="o">.</span><span class="n">re_pytokens</span><span class="p">,</span> <span class="n">subf</span><span class="p">,</span> <span class="n">code</span><span class="p">)</span>
+</div>
+    <span class="nd">@cached_property</span>
+    <span class="k">def</span> <span class="nf">co</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="k">return</span> <span class="nb">compile</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">filename</span> <span class="ow">or</span> <span class="s">&#39;&lt;string&gt;&#39;</span><span class="p">,</span> <span class="s">&#39;exec&#39;</span><span class="p">)</span>
+
+    <span class="nd">@cached_property</span>
+    <span class="k">def</span> <span class="nf">code</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span> <span class="c"># Current Code indentation</span>
+        <span class="n">lineno</span> <span class="o">=</span> <span class="mi">0</span> <span class="c"># Current line of code</span>
+        <span class="n">ptrbuffer</span> <span class="o">=</span> <span class="p">[]</span> <span class="c"># Buffer for printable strings and token tuple instances</span>
+        <span class="n">codebuffer</span> <span class="o">=</span> <span class="p">[]</span> <span class="c"># Buffer for generated python code</span>
+        <span class="n">multiline</span> <span class="o">=</span> <span class="n">dedent</span> <span class="o">=</span> <span class="n">oneline</span> <span class="o">=</span> <span class="bp">False</span>
+        <span class="n">template</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">source</span> <span class="ow">or</span> <span class="nb">open</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">filename</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
+
+        <span class="k">def</span> <span class="nf">yield_tokens</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
+            <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">part</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">r&#39;\{\{(.*?)\}\}&#39;</span><span class="p">,</span> <span class="n">line</span><span class="p">)):</span>
+                <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span><span class="p">:</span>
+                    <span class="k">if</span> <span class="n">part</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;!&#39;</span><span class="p">):</span> <span class="k">yield</span> <span class="s">&#39;RAW&#39;</span><span class="p">,</span> <span class="n">part</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>
+                    <span class="k">else</span><span class="p">:</span> <span class="k">yield</span> <span class="s">&#39;CMD&#39;</span><span class="p">,</span> <span class="n">part</span>
+                <span class="k">else</span><span class="p">:</span> <span class="k">yield</span> <span class="s">&#39;TXT&#39;</span><span class="p">,</span> <span class="n">part</span>
+
+        <span class="k">def</span> <span class="nf">flush</span><span class="p">():</span> <span class="c"># Flush the ptrbuffer</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="n">ptrbuffer</span><span class="p">:</span> <span class="k">return</span>
+            <span class="n">cline</span> <span class="o">=</span> <span class="s">&#39;&#39;</span>
+            <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">ptrbuffer</span><span class="p">:</span>
+                <span class="k">for</span> <span class="n">token</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">line</span><span class="p">:</span>
+                    <span class="k">if</span> <span class="n">token</span> <span class="o">==</span> <span class="s">&#39;TXT&#39;</span><span class="p">:</span> <span class="n">cline</span> <span class="o">+=</span> <span class="nb">repr</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
+                    <span class="k">elif</span> <span class="n">token</span> <span class="o">==</span> <span class="s">&#39;RAW&#39;</span><span class="p">:</span> <span class="n">cline</span> <span class="o">+=</span> <span class="s">&#39;_str(</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="n">value</span>
+                    <span class="k">elif</span> <span class="n">token</span> <span class="o">==</span> <span class="s">&#39;CMD&#39;</span><span class="p">:</span> <span class="n">cline</span> <span class="o">+=</span> <span class="s">&#39;_escape(</span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="n">value</span>
+                    <span class="n">cline</span> <span class="o">+=</span>  <span class="s">&#39;, &#39;</span>
+                <span class="n">cline</span> <span class="o">=</span> <span class="n">cline</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="s">&#39;</span><span class="se">\\\n</span><span class="s">&#39;</span>
+            <span class="n">cline</span> <span class="o">=</span> <span class="n">cline</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
+            <span class="k">if</span> <span class="n">cline</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\\\\\\\\\\</span><span class="s">n&#39;</span><span class="p">):</span>
+                <span class="n">cline</span> <span class="o">=</span> <span class="n">cline</span><span class="p">[:</span><span class="o">-</span><span class="mi">7</span><span class="p">]</span> <span class="o">+</span> <span class="n">cline</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="c"># &#39;nobr\\\\\n&#39; --&gt; &#39;nobr&#39;</span>
+            <span class="n">cline</span> <span class="o">=</span> <span class="s">&#39;_printlist([&#39;</span> <span class="o">+</span> <span class="n">cline</span> <span class="o">+</span> <span class="s">&#39;])&#39;</span>
+            <span class="k">del</span> <span class="n">ptrbuffer</span><span class="p">[:]</span> <span class="c"># Do this before calling code() again</span>
+            <span class="n">code</span><span class="p">(</span><span class="n">cline</span><span class="p">)</span>
+
+        <span class="k">def</span> <span class="nf">code</span><span class="p">(</span><span class="n">stmt</span><span class="p">):</span>
+            <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">stmt</span><span class="o">.</span><span class="n">splitlines</span><span class="p">():</span>
+                <span class="n">codebuffer</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;  &#39;</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">+</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
+
+        <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">template</span><span class="o">.</span><span class="n">splitlines</span><span class="p">(</span><span class="bp">True</span><span class="p">):</span>
+            <span class="n">lineno</span> <span class="o">+=</span> <span class="mi">1</span>
+            <span class="n">line</span> <span class="o">=</span> <span class="n">touni</span><span class="p">(</span><span class="n">line</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span><span class="p">)</span>
+            <span class="n">sline</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">lstrip</span><span class="p">()</span>
+            <span class="k">if</span> <span class="n">lineno</span> <span class="o">&lt;=</span> <span class="mi">2</span><span class="p">:</span>
+                <span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s">r&quot;%\s*#.*coding[:=]\s*([-\w.]+)&quot;</span><span class="p">,</span> <span class="n">sline</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">m</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">m</span><span class="p">:</span> <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;coding&#39;</span><span class="p">,</span><span class="s">&#39;coding (removed)&#39;</span><span class="p">)</span>
+            <span class="k">if</span> <span class="n">sline</span> <span class="ow">and</span> <span class="n">sline</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;%&#39;</span> <span class="ow">and</span> <span class="n">sline</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="o">!=</span> <span class="s">&#39;</span><span class="si">%%</span><span class="s">&#39;</span><span class="p">:</span>
+                <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;%&#39;</span><span class="p">,</span><span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">lstrip</span><span class="p">()</span> <span class="c"># Full line following the %</span>
+                <span class="n">cline</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">split_comment</span><span class="p">(</span><span class="n">line</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+                <span class="n">cmd</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">r&#39;[^a-zA-Z0-9_]&#39;</span><span class="p">,</span> <span class="n">cline</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
+                <span class="n">flush</span><span class="p">()</span> <span class="c"># You are actually reading this? Good luck, it&#39;s a mess :)</span>
+                <span class="k">if</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">blocks</span> <span class="ow">or</span> <span class="n">multiline</span><span class="p">:</span>
+                    <span class="n">cmd</span> <span class="o">=</span> <span class="n">multiline</span> <span class="ow">or</span> <span class="n">cmd</span>
+                    <span class="n">dedent</span> <span class="o">=</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">dedent_blocks</span> <span class="c"># &quot;else:&quot;</span>
+                    <span class="k">if</span> <span class="n">dedent</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">oneline</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">multiline</span><span class="p">:</span>
+                        <span class="n">cmd</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
+                    <span class="n">code</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
+                    <span class="n">oneline</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">cline</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">)</span> <span class="c"># &quot;if 1: pass&quot;</span>
+                    <span class="n">multiline</span> <span class="o">=</span> <span class="n">cmd</span> <span class="k">if</span> <span class="n">cline</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\\</span><span class="s">&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="bp">False</span>
+                    <span class="k">if</span> <span class="ow">not</span> <span class="n">oneline</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">multiline</span><span class="p">:</span>
+                        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
+                <span class="k">elif</span> <span class="n">cmd</span> <span class="o">==</span> <span class="s">&#39;end&#39;</span> <span class="ow">and</span> <span class="n">stack</span><span class="p">:</span>
+                    <span class="n">code</span><span class="p">(</span><span class="s">&#39;#end(</span><span class="si">%s</span><span class="s">) </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">(),</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()[</span><span class="mi">3</span><span class="p">:]))</span>
+                <span class="k">elif</span> <span class="n">cmd</span> <span class="o">==</span> <span class="s">&#39;include&#39;</span><span class="p">:</span>
+                    <span class="n">p</span> <span class="o">=</span> <span class="n">cline</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="mi">2</span><span class="p">)[</span><span class="mi">1</span><span class="p">:]</span>
+                    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
+                        <span class="n">code</span><span class="p">(</span><span class="s">&quot;_=_include(</span><span class="si">%s</span><span class="s">, _stdout, </span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
+                    <span class="k">elif</span> <span class="n">p</span><span class="p">:</span>
+                        <span class="n">code</span><span class="p">(</span><span class="s">&quot;_=_include(</span><span class="si">%s</span><span class="s">, _stdout)&quot;</span> <span class="o">%</span> <span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
+                    <span class="k">else</span><span class="p">:</span> <span class="c"># Empty %include -&gt; reverse of %rebase</span>
+                        <span class="n">code</span><span class="p">(</span><span class="s">&quot;_printlist(_base)&quot;</span><span class="p">)</span>
+                <span class="k">elif</span> <span class="n">cmd</span> <span class="o">==</span> <span class="s">&#39;rebase&#39;</span><span class="p">:</span>
+                    <span class="n">p</span> <span class="o">=</span> <span class="n">cline</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="mi">2</span><span class="p">)[</span><span class="mi">1</span><span class="p">:]</span>
+                    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
+                        <span class="n">code</span><span class="p">(</span><span class="s">&quot;globals()[&#39;_rebase&#39;]=(</span><span class="si">%s</span><span class="s">, dict(</span><span class="si">%s</span><span class="s">))&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>
+                    <span class="k">elif</span> <span class="n">p</span><span class="p">:</span>
+                        <span class="n">code</span><span class="p">(</span><span class="s">&quot;globals()[&#39;_rebase&#39;]=(</span><span class="si">%s</span><span class="s">, {})&quot;</span> <span class="o">%</span> <span class="nb">repr</span><span class="p">(</span><span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]))</span>
+                <span class="k">else</span><span class="p">:</span>
+                    <span class="n">code</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
+            <span class="k">else</span><span class="p">:</span> <span class="c"># Line starting with text (not &#39;%&#39;) or &#39;%%&#39; (escaped)</span>
+                <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%%</span><span class="s">&#39;</span><span class="p">):</span>
+                    <span class="n">line</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%%</span><span class="s">&#39;</span><span class="p">,</span> <span class="s">&#39;%&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+                <span class="n">ptrbuffer</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">yield_tokens</span><span class="p">(</span><span class="n">line</span><span class="p">))</span>
+        <span class="n">flush</span><span class="p">()</span>
+        <span class="k">return</span> <span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">codebuffer</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span>
+
+    <span class="k">def</span> <span class="nf">subtemplate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_name</span><span class="p">,</span> <span class="n">_stdout</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="k">if</span> <span class="n">_name</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">:</span>
+            <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="n">_name</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">_name</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">lookup</span><span class="p">)</span>
+        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span><span class="p">[</span><span class="n">_name</span><span class="p">]</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">_stdout</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_stdout</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="n">env</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">defaults</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
+        <span class="n">env</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s">&#39;_stdout&#39;</span><span class="p">:</span> <span class="n">_stdout</span><span class="p">,</span> <span class="s">&#39;_printlist&#39;</span><span class="p">:</span> <span class="n">_stdout</span><span class="o">.</span><span class="n">extend</span><span class="p">,</span>
+               <span class="s">&#39;_include&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">subtemplate</span><span class="p">,</span> <span class="s">&#39;_str&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_str</span><span class="p">,</span>
+               <span class="s">&#39;_escape&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_escape</span><span class="p">,</span> <span class="s">&#39;get&#39;</span><span class="p">:</span> <span class="n">env</span><span class="o">.</span><span class="n">get</span><span class="p">,</span>
+               <span class="s">&#39;setdefault&#39;</span><span class="p">:</span> <span class="n">env</span><span class="o">.</span><span class="n">setdefault</span><span class="p">,</span> <span class="s">&#39;defined&#39;</span><span class="p">:</span> <span class="n">env</span><span class="o">.</span><span class="n">__contains__</span><span class="p">})</span>
+        <span class="n">env</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
+        <span class="nb">eval</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">co</span><span class="p">,</span> <span class="n">env</span><span class="p">)</span>
+        <span class="k">if</span> <span class="s">&#39;_rebase&#39;</span> <span class="ow">in</span> <span class="n">env</span><span class="p">:</span>
+            <span class="n">subtpl</span><span class="p">,</span> <span class="n">rargs</span> <span class="o">=</span> <span class="n">env</span><span class="p">[</span><span class="s">&#39;_rebase&#39;</span><span class="p">]</span>
+            <span class="n">rargs</span><span class="p">[</span><span class="s">&#39;_base&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">_stdout</span><span class="p">[:]</span> <span class="c">#copy stdout</span>
+            <span class="k">del</span> <span class="n">_stdout</span><span class="p">[:]</span> <span class="c"># clear stdout</span>
+            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">subtemplate</span><span class="p">(</span><span class="n">subtpl</span><span class="p">,</span><span class="n">_stdout</span><span class="p">,</span><span class="n">rargs</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">env</span>
+
+<div class="viewcode-block" id="SimpleTemplate.render"><a class="viewcode-back" href="../stpl.html#bottle.SimpleTemplate.render">[docs]</a>    <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="sd">&quot;&quot;&quot; Render the template using keyword arguments as local variables. &quot;&quot;&quot;</span>
+        <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+        <span class="n">stdout</span> <span class="o">=</span> <span class="p">[]</span>
+        <span class="bp">self</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
+        <span class="k">return</span> <span class="s">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">stdout</span><span class="p">)</span>
+
+</div></div>
+<div class="viewcode-block" id="template"><a class="viewcode-back" href="../api.html#bottle.template">[docs]</a><span class="k">def</span> <span class="nf">template</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39;</span>
+<span class="sd">    Get a rendered template as a string iterator.</span>
+<span class="sd">    You can use a name, a filename or a template string as first parameter.</span>
+<span class="sd">    Template rendering arguments can be passed as dictionaries</span>
+<span class="sd">    or directly (as keyword arguments).</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+    <span class="n">tpl</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">args</span> <span class="k">else</span> <span class="bp">None</span>
+    <span class="n">adapter</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;template_adapter&#39;</span><span class="p">,</span> <span class="n">SimpleTemplate</span><span class="p">)</span>
+    <span class="n">lookup</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;template_lookup&#39;</span><span class="p">,</span> <span class="n">TEMPLATE_PATH</span><span class="p">)</span>
+    <span class="n">tplid</span> <span class="o">=</span> <span class="p">(</span><span class="nb">id</span><span class="p">(</span><span class="n">lookup</span><span class="p">),</span> <span class="n">tpl</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">tpl</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">TEMPLATES</span> <span class="ow">or</span> <span class="n">DEBUG</span><span class="p">:</span>
+        <span class="n">settings</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">&#39;template_settings&#39;</span><span class="p">,</span> <span class="p">{})</span>
+        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">tpl</span><span class="p">,</span> <span class="n">adapter</span><span class="p">):</span>
+            <span class="n">TEMPLATES</span><span class="p">[</span><span class="n">tplid</span><span class="p">]</span> <span class="o">=</span> <span class="n">tpl</span>
+            <span class="k">if</span> <span class="n">settings</span><span class="p">:</span> <span class="n">TEMPLATES</span><span class="p">[</span><span class="n">tplid</span><span class="p">]</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="o">**</span><span class="n">settings</span><span class="p">)</span>
+        <span class="k">elif</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span> <span class="ow">in</span> <span class="n">tpl</span> <span class="ow">or</span> <span class="s">&quot;{&quot;</span> <span class="ow">in</span> <span class="n">tpl</span> <span class="ow">or</span> <span class="s">&quot;%&quot;</span> <span class="ow">in</span> <span class="n">tpl</span> <span class="ow">or</span> <span class="s">&#39;$&#39;</span> <span class="ow">in</span> <span class="n">tpl</span><span class="p">:</span>
+            <span class="n">TEMPLATES</span><span class="p">[</span><span class="n">tplid</span><span class="p">]</span> <span class="o">=</span> <span class="n">adapter</span><span class="p">(</span><span class="n">source</span><span class="o">=</span><span class="n">tpl</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="n">lookup</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">)</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">TEMPLATES</span><span class="p">[</span><span class="n">tplid</span><span class="p">]</span> <span class="o">=</span> <span class="n">adapter</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">tpl</span><span class="p">,</span> <span class="n">lookup</span><span class="o">=</span><span class="n">lookup</span><span class="p">,</span> <span class="o">**</span><span class="n">settings</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">TEMPLATES</span><span class="p">[</span><span class="n">tplid</span><span class="p">]:</span>
+        <span class="n">abort</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s">&#39;Template (</span><span class="si">%s</span><span class="s">) not found&#39;</span> <span class="o">%</span> <span class="n">tpl</span><span class="p">)</span>
+    <span class="k">for</span> <span class="n">dictarg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">dictarg</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">TEMPLATES</span><span class="p">[</span><span class="n">tplid</span><span class="p">]</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
+</div>
+<span class="n">mako_template</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">template</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">MakoTemplate</span><span class="p">)</span>
+<span class="n">cheetah_template</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">template</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">CheetahTemplate</span><span class="p">)</span>
+<span class="n">jinja2_template</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">template</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">Jinja2Template</span><span class="p">)</span>
+<span class="n">simpletal_template</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">template</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">SimpleTALTemplate</span><span class="p">)</span>
+
+
+<div class="viewcode-block" id="view"><a class="viewcode-back" href="../api.html#bottle.view">[docs]</a><span class="k">def</span> <span class="nf">view</span><span class="p">(</span><span class="n">tpl_name</span><span class="p">,</span> <span class="o">**</span><span class="n">defaults</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Decorator: renders a template for a handler.</span>
+<span class="sd">        The handler can control its behavior like that:</span>
+
+<span class="sd">          - return a dict of template vars to fill out the template</span>
+<span class="sd">          - return something other than a dict and the view decorator will not</span>
+<span class="sd">            process the template, but return the handler result as is.</span>
+<span class="sd">            This includes returning a HTTPResponse(dict) to get,</span>
+<span class="sd">            for instance, JSON with autojson or other castfilters.</span>
+<span class="sd">    &#39;&#39;&#39;</span>
+    <span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
+        <span class="nd">@functools.wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+            <span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+            <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">result</span><span class="p">,</span> <span class="p">(</span><span class="nb">dict</span><span class="p">,</span> <span class="n">DictMixin</span><span class="p">)):</span>
+                <span class="n">tplvars</span> <span class="o">=</span> <span class="n">defaults</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
+                <span class="n">tplvars</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
+                <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="n">tpl_name</span><span class="p">,</span> <span class="o">**</span><span class="n">tplvars</span><span class="p">)</span>
+            <span class="k">return</span> <span class="n">result</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+    <span class="k">return</span> <span class="n">decorator</span>
+</div>
+<span class="n">mako_view</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">MakoTemplate</span><span class="p">)</span>
+<span class="n">cheetah_view</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">CheetahTemplate</span><span class="p">)</span>
+<span class="n">jinja2_view</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">Jinja2Template</span><span class="p">)</span>
+<span class="n">simpletal_view</span> <span class="o">=</span> <span class="n">functools</span><span class="o">.</span><span class="n">partial</span><span class="p">(</span><span class="n">view</span><span class="p">,</span> <span class="n">template_adapter</span><span class="o">=</span><span class="n">SimpleTALTemplate</span><span class="p">)</span>
+
+
+
+
+
+
+<span class="c">###############################################################################</span>
+<span class="c"># Constants and Globals ########################################################</span>
+<span class="c">###############################################################################</span>
+
+
+<span class="n">TEMPLATE_PATH</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;./&#39;</span><span class="p">,</span> <span class="s">&#39;./views/&#39;</span><span class="p">]</span>
+<span class="n">TEMPLATES</span> <span class="o">=</span> <span class="p">{}</span>
+<span class="n">DEBUG</span> <span class="o">=</span> <span class="bp">False</span>
+<span class="n">NORUN</span> <span class="o">=</span> <span class="bp">False</span> <span class="c"># If set, run() does nothing. Used by load_app()</span>
+
+<span class="c">#: A dict to map HTTP status codes (e.g. 404) to phrases (e.g. &#39;Not Found&#39;)</span>
+<span class="n">HTTP_CODES</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">responses</span>
+<span class="n">HTTP_CODES</span><span class="p">[</span><span class="mi">418</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;I&#39;m a teapot&quot;</span> <span class="c"># RFC 2324</span>
+<span class="n">HTTP_CODES</span><span class="p">[</span><span class="mi">428</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Precondition Required&quot;</span>
+<span class="n">HTTP_CODES</span><span class="p">[</span><span class="mi">429</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Too Many Requests&quot;</span>
+<span class="n">HTTP_CODES</span><span class="p">[</span><span class="mi">431</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Request Header Fields Too Large&quot;</span>
+<span class="n">HTTP_CODES</span><span class="p">[</span><span class="mi">511</span><span class="p">]</span> <span class="o">=</span> <span class="s">&quot;Network Authentication Required&quot;</span>
+<span class="n">_HTTP_STATUS_LINES</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="s">&#39;</span><span class="si">%d</span><span class="s"> </span><span class="si">%s</span><span class="s">&#39;</span><span class="o">%</span><span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="p">))</span> <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="n">HTTP_CODES</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
+
+<span class="c">#: The default template used for error pages. Override with @error()</span>
+<span class="n">ERROR_PAGE_TEMPLATE</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;</span>
+<span class="si">%%</span><span class="s">try:</span>
+<span class="s">    </span><span class="si">%%</span><span class="s">from </span><span class="si">%s</span><span class="s"> import DEBUG, HTTP_CODES, request, touni</span>
+<span class="s">    &lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML 2.0//EN&quot;&gt;</span>
+<span class="s">    &lt;html&gt;</span>
+<span class="s">        &lt;head&gt;</span>
+<span class="s">            &lt;title&gt;Error: {{e.status}}&lt;/title&gt;</span>
+<span class="s">            &lt;style type=&quot;text/css&quot;&gt;</span>
+<span class="s">              html {background-color: #eee; font-family: sans;}</span>
+<span class="s">              body {background-color: #fff; border: 1px solid #ddd;</span>
+<span class="s">                    padding: 15px; margin: 15px;}</span>
+<span class="s">              pre {background-color: #eee; border: 1px solid #ddd; padding: 5px;}</span>
+<span class="s">            &lt;/style&gt;</span>
+<span class="s">        &lt;/head&gt;</span>
+<span class="s">        &lt;body&gt;</span>
+<span class="s">            &lt;h1&gt;Error: {{e.status}}&lt;/h1&gt;</span>
+<span class="s">            &lt;p&gt;Sorry, the requested URL &lt;tt&gt;{{repr(request.url)}}&lt;/tt&gt;</span>
+<span class="s">               caused an error:&lt;/p&gt;</span>
+<span class="s">            &lt;pre&gt;{{e.body}}&lt;/pre&gt;</span>
+<span class="s">            </span><span class="si">%%</span><span class="s">if DEBUG and e.exception:</span>
+<span class="s">              &lt;h2&gt;Exception:&lt;/h2&gt;</span>
+<span class="s">              &lt;pre&gt;{{repr(e.exception)}}&lt;/pre&gt;</span>
+<span class="s">            </span><span class="si">%%</span><span class="s">end</span>
+<span class="s">            </span><span class="si">%%</span><span class="s">if DEBUG and e.traceback:</span>
+<span class="s">              &lt;h2&gt;Traceback:&lt;/h2&gt;</span>
+<span class="s">              &lt;pre&gt;{{e.traceback}}&lt;/pre&gt;</span>
+<span class="s">            </span><span class="si">%%</span><span class="s">end</span>
+<span class="s">        &lt;/body&gt;</span>
+<span class="s">    &lt;/html&gt;</span>
+<span class="si">%%</span><span class="s">except ImportError:</span>
+<span class="s">    &lt;b&gt;ImportError:&lt;/b&gt; Could not generate the error page. Please add bottle to</span>
+<span class="s">    the import path.</span>
+<span class="si">%%</span><span class="s">end</span>
+<span class="s">&quot;&quot;&quot;</span> <span class="o">%</span> <span class="n">__name__</span>
+
+<span class="c">#: A thread-safe instance of :class:`LocalRequest`. If accessed from within a</span>
+<span class="c">#: request callback, this instance always refers to the *current* request</span>
+<span class="c">#: (even on a multithreaded server).</span>
+<span class="n">request</span> <span class="o">=</span> <span class="n">LocalRequest</span><span class="p">()</span>
+
+<span class="c">#: A thread-safe instance of :class:`LocalResponse`. It is used to change the</span>
+<span class="c">#: HTTP response for the *current* request.</span>
+<span class="n">response</span> <span class="o">=</span> <span class="n">LocalResponse</span><span class="p">()</span>
+
+<span class="c">#: A thread-safe namespace. Not used by Bottle.</span>
+<span class="n">local</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">local</span><span class="p">()</span>
+
+<span class="c"># Initialize app stack (create first empty Bottle app)</span>
+<span class="c"># BC: 0.6.4 and needed for run()</span>
+<span class="n">app</span> <span class="o">=</span> <span class="n">default_app</span> <span class="o">=</span> <span class="n">AppStack</span><span class="p">()</span>
+<span class="n">app</span><span class="o">.</span><span class="n">push</span><span class="p">()</span>
+
+<span class="c">#: A virtual package that redirects import statements.</span>
+<span class="c">#: Example: ``import bottle.ext.sqlite`` actually imports `bottle_sqlite`.</span>
+<span class="n">ext</span> <span class="o">=</span> <span class="n">_ImportRedirect</span><span class="p">(</span><span class="s">&#39;bottle.ext&#39;</span> <span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span> <span class="k">else</span> <span class="n">__name__</span><span class="o">+</span><span class="s">&quot;.ext&quot;</span><span class="p">,</span> <span class="s">&#39;bottle_</span><span class="si">%s</span><span class="s">&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">module</span>
+
+<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
+    <span class="n">opt</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">parser</span> <span class="o">=</span> <span class="n">_cmd_options</span><span class="p">,</span> <span class="n">_cmd_args</span><span class="p">,</span> <span class="n">_cmd_parser</span>
+    <span class="k">if</span> <span class="n">opt</span><span class="o">.</span><span class="n">version</span><span class="p">:</span>
+        <span class="n">_stdout</span><span class="p">(</span><span class="s">&#39;Bottle </span><span class="si">%s</span><span class="se">\n</span><span class="s">&#39;</span><span class="o">%</span><span class="n">__version__</span><span class="p">)</span>
+        <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">args</span><span class="p">:</span>
+        <span class="n">parser</span><span class="o">.</span><span class="n">print_help</span><span class="p">()</span>
+        <span class="n">_stderr</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">Error: No application specified.</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
+        <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
+
+    <span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="s">&#39;.&#39;</span><span class="p">)</span>
+    <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="s">&#39;bottle&#39;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="s">&#39;__main__&#39;</span><span class="p">])</span>
+
+    <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="p">(</span><span class="n">opt</span><span class="o">.</span><span class="n">bind</span> <span class="ow">or</span> <span class="s">&#39;localhost&#39;</span><span class="p">),</span> <span class="mi">8080</span>
+    <span class="k">if</span> <span class="s">&#39;:&#39;</span> <span class="ow">in</span> <span class="n">host</span><span class="p">:</span>
+        <span class="n">host</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">host</span><span class="o">.</span><span class="n">rsplit</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
+
+    <span class="n">run</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">host</span><span class="o">=</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="n">server</span><span class="o">=</span><span class="n">opt</span><span class="o">.</span><span class="n">server</span><span class="p">,</span>
+        <span class="n">reloader</span><span class="o">=</span><span class="n">opt</span><span class="o">.</span><span class="n">reload</span><span class="p">,</span> <span class="n">plugins</span><span class="o">=</span><span class="n">opt</span><span class="o">.</span><span class="n">plugin</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="n">opt</span><span class="o">.</span><span class="n">debug</span><span class="p">)</span>
+
+
+
+
+<span class="c"># THE END</span>
+</pre></div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="../index.html">
+              <img class="logo" src="../_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  
+
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="../_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="../search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+
+          <li><a href="index.html" >Module code</a> &raquo;</li> 
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs__modules/bottle';
+      var disqus_title = 'bottle';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="../index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="../contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/_modules/index.html b/html/_modules/index.html
new file mode 100644 (file)
index 0000000..d4fd43b
--- /dev/null
@@ -0,0 +1,157 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Overview: module code &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="../_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '../',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="../_static/jquery.js"></script>
+    <script type="text/javascript" src="../_static/underscore.js"></script>
+    <script type="text/javascript" src="../_static/doctools.js"></script>
+    <link rel="shortcut icon" href="../_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="../index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="../_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="../_static/logo_reddit.png" />
+    <script type="application/javascript" src="../_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <h1>All modules for which code is available</h1>
+<ul><li><a href="bottle.html">bottle</a></li>
+<li><a href="stpl.html">stpl</a></li>
+</ul>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="../index.html">
+              <img class="logo" src="../_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  
+
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="../_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="../search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs__modules/index';
+      var disqus_title = 'Overview: module code';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="../index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="../contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/_sources/api.txt b/html/_sources/api.txt
new file mode 100644 (file)
index 0000000..aeb4ff0
--- /dev/null
@@ -0,0 +1,193 @@
+==============================
+API Reference
+==============================
+
+.. module:: bottle
+   :platform: Unix, Windows
+   :synopsis: WSGI micro framework
+.. moduleauthor:: Marcel Hellkamp <marc@gsites.de>
+
+This is a mostly auto-generated API. If you are new to bottle, you might find the
+narrative :doc:`tutorial` more helpful.
+
+
+
+
+Module Contents
+=====================================
+
+The module defines several functions, constants, and an exception.
+
+.. autofunction:: debug
+
+.. autofunction:: run
+
+.. autofunction:: load
+
+.. autofunction:: load_app
+
+.. autodata:: request
+
+.. autodata:: response
+
+.. autodata:: HTTP_CODES
+
+.. function:: app()
+              default_app()
+
+    Return the current :ref:`default-app`. Actually, these are callable instances of :class:`AppStack` and implement a stack-like API.
+
+
+Routing
+-------------------
+
+Bottle maintains a stack of :class:`Bottle` instances (see :func:`app` and :class:`AppStack`) and uses the top of the stack as a *default application* for some of the module-level functions and decorators.
+
+
+.. function:: route(path, method='GET', callback=None, **options)
+              get(...)
+              post(...)
+              put(...)
+              delete(...)
+
+   Decorator to install a route to the current default application. See :meth:`Bottle.route` for details.
+
+
+.. function:: error(...)
+
+   Decorator to install an error handler to the current default application. See :meth:`Bottle.error` for details.
+
+
+WSGI and HTTP Utilities
+----------------------------
+
+.. autofunction:: parse_date
+
+.. autofunction:: parse_auth
+
+.. autofunction:: cookie_encode
+
+.. autofunction:: cookie_decode
+
+.. autofunction:: cookie_is_encoded
+
+.. autofunction:: yieldroutes
+
+.. autofunction:: path_shift
+
+
+Data Structures
+----------------------
+
+.. autoclass:: MultiDict
+   :members:
+
+.. autoclass:: HeaderDict
+   :members:
+
+.. autoclass:: FormsDict
+   :members:
+
+.. autoclass:: WSGIHeaderDict
+   :members:
+
+.. autoclass:: AppStack
+   :members:
+
+   .. method:: pop()
+
+      Return the current default application and remove it from the stack.
+
+.. autoclass:: ResourceManager
+   :members:
+
+Exceptions
+---------------
+
+.. autoexception:: BottleException
+   :members:
+
+
+
+The :class:`Bottle` Class
+=========================
+
+.. autoclass:: Bottle
+   :members:
+
+.. autoclass:: Route
+    :members:
+
+
+The :class:`Request` Object
+===================================================
+
+The :class:`Request` class wraps a WSGI environment and provides helpful methods to parse and access form data, cookies, file uploads and other metadata. Most of the attributes are read-only.
+
+.. autoclass:: Request
+   :members:
+
+.. autoclass:: BaseRequest
+   :members:
+
+The module-level :data:`bottle.request` is a proxy object (implemented in :class:`LocalRequest`) and always refers to the `current` request, or in other words, the request that is currently processed by the request handler in the current thread. This `thread locality` ensures that you can safely use a global instance in a multi-threaded environment.
+
+.. autoclass:: LocalRequest
+   :members:
+
+
+The :class:`Response` Object
+===================================================
+
+The :class:`Response` class stores the HTTP status code as well as headers and cookies that are to be sent to the client. Similar to :data:`bottle.request` there is a thread-local :data:`bottle.response` instance that can be used to adjust the `current` response. Moreover, you can instantiate :class:`Response` and return it from your request handler. In this case, the custom instance overrules the headers and cookies defined in the global one.
+
+.. autoclass:: Response
+   :members:
+
+.. autoclass:: BaseResponse
+   :members:
+
+.. autoclass:: LocalResponse
+   :members:
+
+
+The following two classes can be raised as an exception. The most noticeable difference is that bottle invokes error handlers for :class:`HTTPError`, but not for :class:`HTTPResponse` or other response types.
+
+.. autoexception:: HTTPResponse
+   :members:
+
+.. autoexception:: HTTPError
+   :members:
+
+
+
+
+Templates
+=========
+
+All template engines supported by :mod:`bottle` implement the :class:`BaseTemplate` API. This way it is possible to switch and mix template engines without changing the application code at all.
+
+.. autoclass:: BaseTemplate
+   :members:
+
+   .. automethod:: __init__
+
+.. autofunction:: view
+
+.. autofunction:: template
+
+You can write your own adapter for your favourite template engine or use one of the predefined adapters. Currently there are four fully supported template engines:
+
+========================   ===============================   ====================   ========================
+Class                      URL                               Decorator              Render function
+========================   ===============================   ====================   ========================
+:class:`SimpleTemplate`    :doc:`stpl`                       :func:`view`           :func:`template`
+:class:`MakoTemplate`      http://www.makotemplates.org      :func:`mako_view`      :func:`mako_template`
+:class:`CheetahTemplate`   http://www.cheetahtemplate.org/   :func:`cheetah_view`   :func:`cheetah_template`
+:class:`Jinja2Template`    http://jinja.pocoo.org/           :func:`jinja2_view`    :func:`jinja2_template`
+========================   ===============================   ====================   ========================
+
+To use :class:`MakoTemplate` as your default template engine, just import its specialised decorator and render function::
+
+  from bottle import mako_view as view, mako_template as template
+
diff --git a/html/_sources/async.txt b/html/_sources/async.txt
new file mode 100644 (file)
index 0000000..c6c39e9
--- /dev/null
@@ -0,0 +1,127 @@
+Primer to Asynchronous Applications
+===================================
+
+Asynchronous design patterns don't mix well with the synchronous nature of `WSGI <http://www.python.org/dev/peps/pep-3333/>`_. This is why most asynchronous frameworks (tornado, twisted, ...) implement a specialized API to expose their asynchronous features. Bottle is a WSGI framework and shares the synchronous nature of WSGI, but thanks to the awesome `gevent project <http://www.gevent.org/>`_, it is still possible to write asynchronous applications with bottle. This article documents the usage of Bottle with Asynchronous WSGI.
+
+The Limits of Synchronous WSGI
+-------------------------------
+
+Briefly worded, the `WSGI specification (pep 3333) <http://www.python.org/dev/peps/pep-3333/>`_ defines a request/response circle as follows: The application callable is invoked once for each request and must return a body iterator. The server then iterates over the body and writes each chunk to the socket. As soon as the body iterator is exhausted, the client connection is closed.
+
+Simple enough, but there is a snag: All this happens synchronously. If your application needs to wait for data (IO, sockets, databases, ...), it must either yield empty strings (busy wait) or block the current thread. Both solutions occupy the handling thread and prevent it from answering new requests. There is consequently only one ongoing request per thread.
+
+Most servers limit the number of threads to avoid their relatively high overhead. Pools of 20 or less threads are common. As soon as all threads are occupied, any new connection is stalled. The server is effectively dead for everyone else. If you want to implement a chat that uses long-polling ajax requests to get real-time updates, you'd reach the limited at 20 concurrent connections. That's a pretty small chat.
+
+Greenlets to the rescue
+------------------------
+
+Most servers limit the size of their worker pools to a relatively low number of concurrent threads, due to the high overhead involved in switching between and creating new threads. While threads are cheap compared to processes (forks), they are still expensive to create for each new connection.
+
+The `gevent <http://www.gevent.org/>`_ module adds *greenlets* to the mix. Greenlets behave similar to traditional threads, but are very cheap to create. A gevent-based server can spawn thousands of greenlets (one for each connection) with almost no overhead. Blocking individual greenlets has no impact on the servers ability to accept new requests. The number of concurrent connections is virtually unlimited.
+
+This makes creating asynchronous applications incredibly easy, because they look and feel like synchronous applications. A gevent-based server is actually not asynchronous, but massively multi-threaded. Here is an example::
+
+    from gevent import monkey; monkey.patch_all()
+
+    from time import sleep
+    from bottle import route, run
+
+    @route('/stream')
+    def stream():
+        yield 'START'
+        sleep(3)
+        yield 'MIDDLE'
+        sleep(5)
+        yield 'END'
+
+    run(host='0.0.0.0', port=8080, server='gevent')
+
+The first line is important. It causes gevent to monkey-patch most of Python's blocking APIs to not block the current thread, but pass the CPU to the next greenlet instead. It actually replaces Python's threading with gevent-based pseudo-threads. This is why you can still use ``time.sleep()`` which would normally block the whole thread. If you don't feel comfortable with monkey-patching python built-ins, you can use the corresponding gevent functions (``gevent.sleep()`` in this case).
+
+If you run this script and point your browser to ``http://localhost:8080/stream``, you should see `START`, `MIDDLE`, and `END` show up one by one (rather than waiting 8 seconds to see them all at once). It works exactly as with normal threads, but now your server can handle thousands of concurrent requests without any problems.
+
+.. note::
+
+    Some browsers buffer a certain amount of data before they start rendering a
+    page. You might need to yield more than a few bytes to see an effect in
+    these browsers. Additionally, many browsers have a limit of one concurrent
+    connection per URL. If this is the case, you can use a second browser or a
+    benchmark tool (e.g. `ab` or `httperf`) to measure performance.
+
+Event Callbacks
+---------------
+
+A very common design pattern in asynchronous frameworks (including tornado, twisted, node.js and friends) is to use non-blocking APIs and bind callbacks to asynchronous events. The socket object is kept open until it is closed explicitly to allow callbacks to write to the socket at a later point. Here is an example based on the `tornado library <http://www.tornadoweb.org/documentation#non-blocking-asynchronous-requests>`_::
+
+    class MainHandler(tornado.web.RequestHandler):
+        @tornado.web.asynchronous
+        def get(self):
+            worker = SomeAsyncWorker()
+            worker.on_data(lambda chunk: self.write(chunk))
+            worker.on_finish(lambda: self.finish())
+
+The main benefit is that the request handler terminates early. The handling thread can move on and accept new requests while the callbacks continue to write to sockets of previous requests. This is how these frameworks manage to process a lot of concurrent requests with only a small number of OS threads.
+
+With Gevent+WSGI, things are different: First, terminating early has no benefit because we have an unlimited pool of (pseudo)threads to accept new connections. Second, we cannot terminate early because that would close the socket (as required by WSGI). Third, we must return an iterable to conform to WSGI.
+
+In order to conform to the WSGI standard, all we have to do is to return a body iterable that we can write to asynchronously. With the help of `gevent.queue <http://www.gevent.org/gevent.queue.html>`_, we can *simulate* a detached socket and rewrite the previous example as follows::
+
+    @route('/fetch')
+    def fetch():
+        body = gevent.queue.Queue()
+        worker = SomeAsyncWorker()
+        worker.on_data(lambda chunk: body.put(chunk))
+        worker.on_finish(lambda: body.put(StopIteration))
+        return body
+
+From the server perspective, the queue object is iterable. It blocks if empty and stops as soon as it reaches ``StopIteration``. This conforms to WSGI. On the application side, the queue object behaves like a non-blocking socket. You can write to it at any time, pass it around and even start a new (pseudo)thread that writes to it asynchronously. This is how long-polling is implemented most of the time.
+
+
+Finally: WebSockets
+-------------------
+
+Lets forget about the low-level details for a while and speak about WebSockets. Since you are reading this article, you probably know what WebSockets are: A bidirectional communication channel between a browser (client) and a web application (server).
+
+Thankfully the `gevent-websocket <http://pypi.python.org/pypi/gevent-websocket/>`_ package does all the hard work for us. Here is a simple WebSocket endpoint that receives messages and just sends them back to the client::
+
+    from bottle import request, Bottle, abort
+    app = Bottle()
+
+    @app.route('/websocket')
+    def handle_websocket():
+        wsock = request.environ.get('wsgi.websocket')
+        if not wsock:
+            abort(400, 'Expected WebSocket request.')
+
+        while True:
+            try:
+                message = wsock.receive()
+                wsock.send("Your message was: %r" % message)
+            except WebSocketError:
+                break
+
+    from gevent.pywsgi import WSGIServer
+    from geventwebsocket import WebSocketHandler, WebSocketError
+    server = WSGIServer(("0.0.0.0", 8080), app,
+                        handler_class=WebSocketHandler)
+    server.serve_forever()
+
+The while-loop runs until the client closes the connection. You get the idea :)
+
+The client-site JavaScript API is really straight forward, too::
+
+    <!DOCTYPE html>
+    <html>
+    <head>
+      <script type="text/javascript">
+        var ws = new WebSocket("ws://example.com:8080/websocket");
+        ws.onopen = function() {
+            ws.send("Hello, world");
+        };
+        ws.onmessage = function (evt) {
+            alert(evt.data);
+        };
+      </script>
+    </head>
+    </html>
+
diff --git a/html/_sources/changelog.txt b/html/_sources/changelog.txt
new file mode 100644 (file)
index 0000000..44a37f4
--- /dev/null
@@ -0,0 +1,141 @@
+.. highlight:: python
+.. currentmodule:: bottle
+
+===========================
+Release Notes and Changelog
+===========================
+
+Release 0.11
+==============
+
+.. warning: Not released yet.
+
+* Native support for Python 2.x and 3.x syntax. No need to run 2to3 anymore.
+* Support for partial downloads (``Range`` header) in :func:`static_file`.
+* The new :class:`ResourceManager` interface helps locating files bundled with an application.
+* Added a server adapter for `waitress <http://docs.pylonsproject.org/projects/waitress/en/latest/>`_.
+* New :meth:`Bottle.merge` method to install all routes from one application into another.
+* New :attr:`BaseRequest.app` property to get the application object that handles a request.
+* Added :meth:`FormsDict.decode()` to get an all-unicode version (needed by WTForms).
+* :class:`MultiDict` and subclasses are now pickle-able.
+
+.. rubric:: API Changes
+
+* :attr:`Response.status` is a read-write property that can be assigned either a numeric status code or a status string with a reason phrase (``200 OK``). The return value is now a string to better match existing APIs (WebOb, werkzeug). To be absolutely clear, you can use the read-only properties :attr:`BaseResponse.status_code` and :attr:`BaseResponse.status_line`.
+
+.. rubric:: API Deprecations
+
+* :class:`SimpleTALTemplate` is now deprecating. There seems to be no demand.
+
+Release 0.10
+==============
+
+* Plugin API v2
+
+  * To use the new API, set :attr:`Plugin.api` to ``2``.
+  * :meth:`Plugin.apply` receives a :class:`Route` object instead of a context dictionary as second parameter. The new object offers some additional information and may be extended in the future.
+  * Plugin names are considered unique now. The topmost plugin with a given name on a given route is installed, all other plugins with the same name are silently ignored.
+
+* The Request/Response Objects
+
+  * Added :attr:`BaseRequest.json`, :attr:`BaseRequest.remote_route`, :attr:`BaseRequest.remote_addr`, :attr:`BaseRequest.query` and :attr:`BaseRequest.script_name`.
+  * Added :attr:`BaseResponse.status_line` and :attr:`BaseResponse.status_code` attributes. In future releases, :attr:`BaseResponse.status` will return a string (e.g. ``200 OK``) instead of an integer to match the API of other common frameworks. To make the transition as smooth as possible, you should use the verbose attributes from now on.
+  * Replaced :class:`MultiDict` with a specialized :class:`FormsDict` in many places. The new dict implementation allows attribute access and handles unicode form values transparently.
+
+* Templates
+
+  * Added three new functions to the SimpleTemplate default namespace that handle undefined variables: :func:`stpl.defined`, :func:`stpl.get` and :func:`stpl.setdefault`.
+  * The default escape function for SimpleTemplate now additionally escapes single and double quotes.
+
+* Routing
+
+  * A new route syntax (e.g. ``/object/<id:int>``) and support for route wildcard filters.
+  * Four new wildcard filters: `int`, `float`, `path` and `re`.
+
+* Oher changes
+
+  * Added command line interface to load applications and start servers.
+  * Introduced a :class:`ConfigDict` that makes accessing configuration a lot easier (attribute access and auto-expanding namespaces).
+  * Added support for raw WSGI applications to :meth:`Bottle.mount`.
+  * :meth:`Bottle.mount` parameter order changed.
+  * :meth:`Bottle.route` now accpets an import string for the ``callback`` parameter.
+  * Dropped Gunicorn 0.8 support. Current supported version is 0.13.
+  * Added custom options to Gunicorn server.
+  * Finally dropped support for type filters. Replace with a custom plugin of needed.
+
+
+Release 0.9
+============
+
+.. rubric:: Whats new?
+
+* A brand new plugin-API. See :ref:`plugins` and :doc:`plugindev` for details.
+* The :func:`route` decorator got a lot of new features. See :meth:`Bottle.route` for details.
+* New server adapters for `gevent <http://www.gevent.org/>`_, `meinheld <http://meinheld.org/>`_ and `bjoern <https://github.com/jonashaag/bjoern>`_.
+* Support for SimpleTAL templates.
+* Better runtime exception handling for mako templates in debug mode.
+* Lots of documentation, fixes and small improvements.
+* A new :data:`Request.urlparts` property.
+
+.. rubric:: Performance improvements
+
+* The :class:`Router` now special-cases ``wsgi.run_once`` environments to speed up CGI.
+* Reduced module load time by ~30% and optimized template parser. See `8ccb2d </commit/8ccb2d>`_, `f72a7c </commit/f72a7c>`_ and `b14b9a </commit/b14b9a>`_ for details.
+* Support for "App Caching" on Google App Engine. See `af93ec </commit/af93ec>`_.
+* Some of the rarely used or deprecated features are now plugins that avoid overhead if the feature is not used.
+
+.. rubric:: API changes
+
+This release is mostly backward compatible, but some APIs are marked deprecated now and will be removed for the next release. Most noteworthy:
+
+* The ``static`` route parameter is deprecated. You can escape wild-cards with a backslash.
+* Type-based output filters are deprecated. They can easily be replaced with plugins.
+
+
+Release 0.8
+============
+
+.. rubric:: API changes
+
+These changes may break compatibility with previous versions.
+
+* The built-in Key/Value database is not available anymore. It is marked deprecated since 0.6.4
+* The Route syntax and behaviour changed.
+
+  * Regular expressions must be encapsulated with ``#``. In 0.6 all non-alphanumeric characters not present in the regular expression were allowed.
+  * Regular expressions not part of a route wildcard are escaped automatically. You don't have to escape dots or other regular control characters anymore. In 0.6 the whole URL was interpreted as a regular expression. You can use anonymous wildcards (``/index:#(\.html)?#``) to achieve a similar behaviour.
+
+* The ``BreakTheBottle`` exception is gone. Use :class:`HTTPResponse` instead.
+* The :class:`SimpleTemplate` engine escapes HTML special characters in ``{{bad_html}}`` expressions automatically. Use the new ``{{!good_html}}`` syntax to get old behaviour (no escaping).
+* The :class:`SimpleTemplate` engine returns unicode strings instead of lists of byte strings.
+* ``bottle.optimize()`` and the automatic route optimization is obsolete.
+* Some functions and attributes were renamed:
+
+  * :attr:`Request._environ` is now :attr:`Request.environ`
+  * :attr:`Response.header` is now :attr:`Response.headers`
+  * :func:`default_app` is obsolete. Use :func:`app` instead.
+
+* The default :func:`redirect` code changed from 307 to 303.
+* Removed support for ``@default``. Use ``@error(404)`` instead.
+
+.. rubric:: New features
+
+
+This is an incomplete list of new features and improved functionality.
+
+* The :class:`Request` object got new properties: :attr:`Request.body`, :attr:`Request.auth`, :attr:`Request.url`, :attr:`Request.header`, :attr:`Request.forms`, :attr:`Request.files`.
+* The :meth:`Response.set_cookie` and :meth:`Request.get_cookie` methods are now able to encode and decode python objects. This is called a *secure cookie* because the encoded values are signed and protected from changes on client side. All pickle-able data structures are allowed.
+* The new :class:`Router` class drastically improves performance for setups with lots of dynamic routes and supports named routes (named route + dict = URL string).
+* It is now possible (and recommended) to return :exc:`HTTPError` and :exc:`HTTPResponse` instances or other exception objects instead of raising them.
+* The new function :func:`static_file` equals :func:`send_file` but returns a :exc:`HTTPResponse` or :exc:`HTTPError` instead of raising it. :func:`send_file` is deprecated.
+* New :func:`get`, :func:`post`, :func:`put` and :func:`delete` decorators.
+* The :class:`SimpleTemplate` engine got full unicode support.
+* Lots of non-critical bugfixes.
+
+
+
+============
+Contributors
+============
+
+.. include:: ../AUTHORS
diff --git a/html/_sources/contact.txt b/html/_sources/contact.txt
new file mode 100644 (file)
index 0000000..7412484
--- /dev/null
@@ -0,0 +1,30 @@
+=============
+Contact
+=============
+
+.. rubric:: About the Autor
+
+.. image:: _static/myface_small.png
+   :alt: Photo
+   :class: floatright
+
+Hi, I'm *Marcel Hellkamp* (aka *defnull*), author of Bottle and the guy behind this website. I'm 27 years old and studying computer science at the Georg-August-University in Göttingen, Germany. Python is my favorite language, but I also code in ruby and JavaScript a lot. Watch me on `twitter <http://twitter.com/bottlepy>`_ or visit my profile at `GitHub <http://github.com/defnull>`_ to get in contact. A `mailinglist <http://groups.google.de/group/bottlepy>`_ is open for Bottle related questions, too.
+
+.. rubric:: About Bottle
+
+This is my first open source project so far. It started and a small experiment but soon got so much positive feedback I decided to make something real out of it. Here it is.
+
+.. rubric:: Impressum und Kontaktdaten
+
+(This is required by `German law <http://bundesrecht.juris.de/tmg/__5.html>`_)
+
+Die Nutzung der folgenden Kontaktdaten ist ausschließlich für die 
+Kontaktaufnahme mit dem Betreiber dieser Webseite bei rechtlichen 
+Problemen vorgesehen. Insbesondere die Nutzung zu Werbe- oder ähnlichen 
+Zwecken ist ausdrücklich untersagt.
+
+  * **Betreiber**: Marcel Hellkamp
+  * **Ort**: D - 37075 Göttingen
+  * **Strasse**: Theodor-Heuss Strasse 13
+  * **Telefon**: +49 (0) 551 20005915
+  * **E-Mail**: marc at gsites dot de
diff --git a/html/_sources/deployment.txt b/html/_sources/deployment.txt
new file mode 100644 (file)
index 0000000..7371ac2
--- /dev/null
@@ -0,0 +1,205 @@
+.. _flup: http://trac.saddi.com/flup
+.. _gae: http://code.google.com/appengine/docs/python/overview.html
+.. _wsgiref: http://docs.python.org/library/wsgiref.html
+.. _cherrypy: http://www.cherrypy.org/
+.. _paste: http://pythonpaste.org/
+.. _rocket: http://pypi.python.org/pypi/rocket
+.. _gunicorn: http://pypi.python.org/pypi/gunicorn
+.. _fapws3: http://www.fapws.org/
+.. _tornado: http://www.tornadoweb.org/
+.. _twisted: http://twistedmatrix.com/
+.. _diesel: http://dieselweb.org/
+.. _meinheld: http://pypi.python.org/pypi/meinheld
+.. _bjoern: http://pypi.python.org/pypi/bjoern
+.. _gevent: http://www.gevent.org/
+.. _eventlet: http://eventlet.net/
+.. _waitress: http://readthedocs.org/docs/waitress/en/latest/
+.. _apache: http://httpd.apache.org/
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
+.. _pound: http://www.apsis.ch/pound
+
+
+
+.. _tutorial-deployment:
+
+================================================================================
+Deployment
+================================================================================
+
+The bottle :func:`run` function, when called without any parameters, starts a local development server on port 8080. You can access and test your application via http://localhost:8080/ if you are on the same host.
+
+To get your application available to the outside world, specify the IP of the interface the server should listen to (e.g. ``run(host='192.168.0.1')``) or let the server listen to all interfaces at once (e.g. ``run(host='0.0.0.0')``). The listening port can be changed in a similar way, but you need root or admin rights to choose a port below 1024. Port 80 is the standard for HTTP servers::
+
+  run(host='0.0.0.0', port=80) # Listen to HTTP requests on all interfaces
+
+Server Options
+================================================================================
+
+The built-in default server is based on `wsgiref WSGIServer <http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server>`_. This non-threading HTTP server is perfectly fine for development and early production, but may become a performance bottleneck when server load increases. There are three ways to eliminate this bottleneck:
+
+* Use a different server that is either multi-threaded or asynchronous.
+* Start multiple server processes and spread the load with a load-balancer.
+* Do both.
+
+**Multi-threaded** servers are the 'classic' way to do it. They are very robust, reasonably fast and easy to manage. As a drawback, they can only handle a limited number of connections at the same time and utilize only one CPU core due to the "Global Interpreter Lock" (GIL). This does not hurt most applications, they are waiting for network IO most of the time anyway, but may slow down CPU intensive tasks (e.g. image processing).
+
+**Asynchronous** servers are very fast, can handle a virtually unlimited number of concurrent connections and are easy to manage, but can get a bit tricky. To take full advantage of their potential, you need to design your application accordingly and understand the concepts of the specific server.
+
+**Multi-processing** (forking) servers are not limited by the GIL and utilize more than one CPU core, but make communication between server instances more expensive. You need a database or external message query to share state between processes, or design your application so that it does not need any shared state. The setup is also a bit more complicated, but there are good tutorials available. 
+
+Switching the Server Backend
+================================================================================
+
+The easiest way to increase performance is to install a multi-threaded server library like paste_ or cherrypy_ and tell Bottle to use that instead of the single-threaded server::
+
+    bottle.run(server='paste')
+
+Bottle ships with a lot of ready-to-use adapters for the most common WSGI servers and automates the setup process. Here is an incomplete list:
+
+========  ============  ======================================================
+Name      Homepage      Description
+========  ============  ======================================================
+cgi                     Run as CGI script
+flup      flup_         Run as FastCGI process
+gae       gae_          Helper for Google App Engine deployments
+wsgiref   wsgiref_      Single-threaded default server
+cherrypy  cherrypy_     Multi-threaded and very stable
+paste     paste_        Multi-threaded, stable, tried and tested
+rocket    rocket_       Multi-threaded
+waitress  waitress_     Multi-threaded, poweres Pyramid
+gunicorn  gunicorn_     Pre-forked, partly written in C
+eventlet  eventlet_     Asynchronous framework with WSGI support.
+gevent    gevent_       Asynchronous (greenlets)
+diesel    diesel_       Asynchronous (greenlets)
+fapws3    fapws3_       Asynchronous (network side only), written in C
+tornado   tornado_      Asynchronous, powers some parts of Facebook
+twisted   twisted_      Asynchronous, well tested but... twisted
+meinheld  meinheld_     Asynchronous, partly written in C
+bjoern    bjoern_       Asynchronous, very fast and written in C
+auto                    Automatically selects an available server adapter
+========  ============  ======================================================
+
+The full list is available through :data:`server_names`.
+
+If there is no adapter for your favorite server or if you need more control over the server setup, you may want to start the server manually. Refer to the server documentation on how to run WSGI applications. Here is an example for paste_::
+
+    application = bottle.default_app()
+    from paste import httpserver
+    httpserver.serve(application, host='0.0.0.0', port=80)
+
+
+
+Apache mod_wsgi
+--------------------------------------------------------------------------------
+
+Instead of running your own HTTP server from within Bottle, you can attach Bottle applications to an `Apache server <apache>`_ using mod_wsgi_.
+
+All you need is an ``app.wsgi`` file that provides an ``application`` object. This object is used by mod_wsgi to start your application and should be a WSGI-compatible Python callable.
+
+File ``/var/www/yourapp/app.wsgi``::
+
+    # Change working directory so relative paths (and template lookup) work again
+    os.chdir(os.path.dirname(__file__))
+    
+    import bottle
+    # ... build or import your bottle application here ...
+    # Do NOT use bottle.run() with mod_wsgi
+    application = bottle.default_app()
+
+The Apache configuration may look like this::
+
+    <VirtualHost *>
+        ServerName example.com
+        
+        WSGIDaemonProcess yourapp user=www-data group=www-data processes=1 threads=5
+        WSGIScriptAlias / /var/www/yourapp/app.wsgi
+        
+        <Directory /var/www/yourapp>
+            WSGIProcessGroup yourapp
+            WSGIApplicationGroup %{GLOBAL}
+            Order deny,allow
+            Allow from all
+        </Directory>
+    </VirtualHost>
+
+
+
+Google AppEngine
+--------------------------------------------------------------------------------
+
+.. versionadded:: 0.9
+
+The ``gae`` server adapter is used to run applications on Google App Engine. It works similar to the ``cgi`` adapter in that it does not start a new HTTP server, but prepares and optimizes your application for Google App Engine and makes sure it conforms to their API::
+
+    bottle.run(server='gae') # No need for a host or port setting.
+
+It is always a good idea to let GAE serve static files directly. Here is example for a working  ``app.yaml``::
+
+    application: myapp
+    version: 1
+    runtime: python
+    api_version: 1
+
+    handlers:
+    - url: /static
+      static_dir: static
+
+    - url: /.*
+      script: myapp.py
+
+
+Load Balancer (Manual Setup)
+--------------------------------------------------------------------------------
+
+A single Python process can utilize only one CPU at a time, even if there are more CPU cores available. The trick is to balance the load between multiple independent Python processes to utilize all of your CPU cores.
+
+Instead of a single Bottle application server, you start one instance for each CPU core available using different local port (localhost:8080, 8081, 8082, ...). You can choose any server adapter you want, even asynchronous ones. Then a high performance load balancer acts as a reverse proxy and forwards each new requests to a random port, spreading the load between all available back-ends. This way you can use all of your CPU cores and even spread out the load between different physical servers.
+
+One of the fastest load balancers available is Pound_ but most common web servers have a proxy-module that can do the work just fine.
+
+Pound example::
+
+    ListenHTTP
+        Address 0.0.0.0
+        Port    80
+
+        Service
+            BackEnd
+                Address 127.0.0.1
+                Port    8080
+            End
+            BackEnd
+                Address 127.0.0.1
+                Port    8081
+            End
+        End
+    End
+
+Apache example::
+
+    <Proxy balancer://mycluster>
+    BalancerMember http://192.168.1.50:80
+    BalancerMember http://192.168.1.51:80
+    </Proxy>
+    ProxyPass / balancer://mycluster 
+
+Lighttpd example::
+
+    server.modules += ( "mod_proxy" )
+    proxy.server = (
+        "" => (
+            "wsgi1" => ( "host" => "127.0.0.1", "port" => 8080 ),
+            "wsgi2" => ( "host" => "127.0.0.1", "port" => 8081 )
+        )
+    )
+
+
+Good old CGI
+================================================================================
+
+A CGI server starts a new process for each request. This adds a lot of overhead but is sometimes the only option, especially on cheap hosting packages. The `cgi` server adapter does not actually start a CGI server, but transforms your bottle application into a valid CGI application::
+
+    bottle.run(server='cgi')
+
+
+
diff --git a/html/_sources/development.txt b/html/_sources/development.txt
new file mode 100644 (file)
index 0000000..91a72fa
--- /dev/null
@@ -0,0 +1,181 @@
+Developer Notes
+=================
+
+This document is intended for developers and package maintainers interested in the bottle development and release workflow. If you want to contribute, you are just right!
+
+
+Get involved
+------------
+
+There are several ways to join the community and stay up to date. Here are some of them:
+
+* **Mailing list**: Join our mailing list by sending an email to `bottlepy+subscribe@googlegroups.com <mailto:bottlepy+subscribe@googlegroups.com>`_ (no google account required).
+* **Twitter**: `Follow us on Twitter <twitter.com/bottlepy>`_ or search for the `#bottlepy <https://twitter.com/#!/search/%23bottlepy>`_ tag.
+* **IRC**: Join `#bottlepy on irc.freenode.net <irc://irc.freenode.net/bottlepy>`_ or use the `web chat interface <http://webchat.freenode.net/?channels=bottlepy>`_.
+* **Google plus**: We sometimes `blog about Bottle, releases and technical stuff <https://plus.google.com/b/104025895326575643538/104025895326575643538/posts>`_ on our Google+ page.
+
+
+Get the Sources
+---------------
+
+The bottle `development repository <https://github.com/defnull/bottle>`_ and the `issue tracker <https://github.com/defnull/bottle/issues>`_ are both hosted at `github <https://github.com/defnull/bottle>`_. If you plan to contribute, it is a good idea to create an account there and fork the main repository. This way your changes and ideas are visible to other developers and can be discussed openly. Even without an account, you can clone the repository or just download the latest development version as a source archive.
+
+* **git:** ``git clone git://github.com/defnull/bottle.git``
+* **git/https:** ``git clone https://github.com/defnull/bottle.git``
+* **Download:** Development branch as `tar archive <http://github.com/defnull/bottle/tarball/master>`_ or `zip file <http://github.com/defnull/bottle/zipball/master>`_.
+
+
+Releases and Updates
+--------------------
+
+Bottle is released at irregular intervals and distributed through `PyPi <http://pypi.python.org/pypi/bottle>`_. Release candidates and bugfix-revisions of outdated releases are only available from the git repository mentioned above. Some Linux distributions may offer packages for outdated releases, though. 
+
+The Bottle version number splits into three parts (**major.minor.revision**). These are *not* used to promote new features but to indicate important bug-fixes and/or API changes. Critical bugs are fixed in at least the two latest minor releases and announced in all available channels (mailinglist, twitter, github). Non-critical bugs or features are not guaranteed to be backported. This may change in the future, through.
+
+Major Release (x.0)
+    The major release number is increased on important milestones or updates that completely break backward compatibility. You probably have to work over your entire application to use a new release. These releases are very rare, through.
+
+Minor Release (x.y)
+    The minor release number is increased on updates that change the API or behaviour in some way. You might get some depreciation warnings any may have to tweak some configuration settings to restore the old behaviour, but in most cases these changes are designed to be backward compatible for at least one minor release. You should update to stay up do date, but don't have to. An exception is 0.8, which *will* break backward compatibility hard. (This is why 0.7 was skipped). Sorry about that.
+
+Revision (x.y.z)
+    The revision number is increased on bug-fixes and other patches that do not change the API or behaviour. You can safely update without editing your application code. In fact, you really should as soon as possible, because important security fixes are released this way.
+
+Pre-Release Versions
+    Release candidates are marked by an ``rc`` in their revision number. These are API stable most of the time and open for testing, but not officially released yet. You should not use these for production.
+
+
+Repository Structure
+--------------------
+
+The source repository is structured as follows:
+
+``master`` branch
+  This is the integration, testing and development branch. All changes that are planned to be part of the next release are merged and tested here.
+
+``release-x.y`` branches
+  As soon as the master branch is (almost) ready for a new release, it is branched into a new release branch. This "release candidate" is feature-frozen but may receive bug-fixes and last-minute changes until it is considered production ready and officially released. From that point on it is called a "support branch" and still receives bug-fixes, but only important ones. The revision number is increased on each push to these branches, so you can keep up with important changes.
+
+``bugfix_name-x.y`` branches
+  These branches are only temporary and used to develop and share non-trivial bug-fixes for existing releases. They are merged into the corresponding release branch and deleted soon after that.
+
+Feature branches
+  All other branches are feature branches. These are based on the master branch and only live as long as they are still active and not merged back into ``master``.
+
+
+.. rubric:: What does this mean for a developer?
+
+If you want to add a feature, create a new branch from ``master``. If you want to fix a bug, branch ``release-x.y`` for each affected release. Please use a separate branch for each feature or bug to make integration as easy as possible. Thats all. There are git workflow examples at the bottom of this page.
+
+Oh, and never ever change the release number. We'll do that on integration. You never know in which order we pull pending requests anyway :)
+
+
+.. rubric:: What does this mean for a maintainer ?
+
+Watch the tags (and the mailing list) for bug-fixes and new releases. If you want to fetch a specific release from the git repository, trust the tags, not the branches. A branch may contain changes that are not released yet, but a tag marks the exact commit which changed the version number.
+
+
+Submitting Patches
+------------------
+
+The best way to get your changes integrated into the main development branch is to fork the main repository at github, create a new feature-branch, apply your changes and send a pull-request. Further down this page is a small collection of git workflow examples that may guide you. Submitting git-compatible patches to the mailing list is fine too. In any case, please follow some basic rules:
+
+* **Documentation:** Tell us what your patch does. Comment your code. If you introduced a new feature, add to the documentation so others can learn about it.
+* **Test:** Write tests to prove that your code works as expected and does not break anything. If you fixed a bug, write at least one test-case that triggers the bug. Make sure that all tests pass before you submit a patch.
+* **One patch at a time:** Only fix one bug or add one feature at a time. Design your patches so that they can be applyed as a whole. Keep your patches clean, small and focused. 
+* **Sync with upstream:** If the ``upstream/master`` branch changed while you were working on your patch, rebase or pull to make sure that your patch still applies without conflicts.
+
+
+Building the Documentation
+--------------------------
+
+You need a recent version of Sphinx to build the documentation. The recommended way is to install :command:`virtualenv` using your distribution package repository and install sphinx manually to get an up-to-date version.
+
+.. code-block:: bash
+
+  # Install prerequisites
+  which virtualenv || sudo apt-get install python-virtualenv
+  virtualenv --no-site-dependencies venv
+  ./venv/pip install -U sphinx
+
+  # Clone or download bottle from github
+  git clone https://github.com/defnull/bottle.git
+
+  # Activate build environment
+  source ./venv/bin/activate
+
+  # Build HTML docs
+  cd bottle/docs
+  make html
+
+  # Optional: Install prerequisites for PDF generation
+  sudo apt-get install texlive-latex-extra \
+                       texlive-latex-recommended \
+                       texlive-fonts-recommended
+
+  # Optional: Build the documentation as PDF
+  make latex
+  cd ../build/docs/latex
+  make pdf
+
+
+GIT Workflow Examples
+---------------------
+
+The following examples assume that you have an (free) `github account <https://github.com>`_. This is not mandatory, but makes things a lot easier.
+
+First of all you need to create a fork (a personal clone) of the official repository. To do this, you simply click the "fork" button on the `bottle project page <https://github.com/defnull/bottle>`_. When the fork is done, you will be presented with a short introduction to your new repository.
+
+The fork you just created is hosted at github and read-able by everyone, but write-able only by you. Now you need to clone the fork locally to actually make changes to it. Make sure you use the private (read-write) URL and *not* the public (read-only) one::
+
+  git clone git@github.com:your_github_account/bottle.git
+
+Once the clone is complete your repository will have a remote named "origin" that points to your fork on github. Don’t let the name confuse you, this does not point to the original bottle repository, but to your own fork. To keep track of the official repository, add another remote named "upstream"::
+
+  cd bottle
+  git remote add upstream git://github.com/defnull/bottle.git
+  git fetch upstream
+
+Note that "upstream" is a public clone URL, which is read-only. You cannot push changes directly to it. Instead, we will pull from your public repository. This is described later.
+
+.. rubric:: Submit a Feature
+
+New features are developed in separate feature-branches to make integration easy. Because they are going to be integrated into the ``master`` branch, they must be based on ``upstream/master``. To create a new feature-branch, type the following::
+
+  git checkout -b cool_feature upstream/master
+  
+Now implement your feature, write tests, update the documentation, make sure that all tests pass and commit your changes::
+
+  git commit -a -m "Cool Feature"
+
+If the ``upstream/master`` branch changed in the meantime, there may be conflicts with your changes. To solve these, 'rebase' your feature-branch onto the top of the updated ``upstream/master`` branch::
+
+  git fetch upstream
+  git rebase upstream
+
+This is equivalent to undoing all your changes, updating your branch to the latest version and reapplying all your patches again. If you released your branch already (see next step), this is not an option because it rewrites your history. You can do a normal pull instead. Resolve any conflicts, run the tests again and commit. 
+
+Now you are almost ready to send a pull request. But first you need to make your feature-branch public by pushing it to your github fork::
+
+  git push origin cool_feature
+
+After you’ve pushed your commit(s) you need to inform us about the new feature. One way is to send a pull-request using github. Another way would be to start a thread in the mailing-list, which is recommended. It allows other developers to see and discuss your patches and you get some feedback for free :)
+
+If we accept your patch, we will integrate it into the official development branch and make it part of the next release.
+
+.. rubric:: Fix a Bug
+
+The workflow for bug-fixes is very similar to the one for features, but there are some differences:
+
+1) Branch off of the affected release branches instead of just the development branch.
+2) Write at least one test-case that triggers the bug.
+3) Do this for each affected branch including ``upstream/master`` if it is affected. ``git cherry-pick`` may help you reducing repetitive work.
+4) Name your branch after the release it is based on to avoid confusion. Examples: ``my_bugfix-x.y`` or ``my_bugfix-dev``.
+
+
+
+
+
+
+
+
diff --git a/html/_sources/faq.txt b/html/_sources/faq.txt
new file mode 100644 (file)
index 0000000..4a025d9
--- /dev/null
@@ -0,0 +1,62 @@
+.. module:: bottle
+
+.. _paste: http://pythonpaste.org/modules/evalexception.html
+.. _pylons: http://pylonshq.com/
+.. _mod_python: http://www.modpython.org/
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
+
+==========================
+Frequently Asked Questions
+==========================
+
+About Bottle
+============
+
+Is bottle suitable for complex applications?
+---------------------------------------------
+
+Bottle is a *micro* framework designed for prototyping and building small web applications and services. It stays out of your way and allows you to get things done fast, but misses some advanced features and ready-to-use solutions found in other frameworks (MVC, ORM, form validation, scaffolding, XML-RPC). Although it *is* possible to add these features and build complex applications with Bottle, you should consider using a full-stack Web framework like pylons_ or paste_ instead.
+
+
+Common Problems and Pitfalls
+============================
+
+
+
+
+
+"Template Not Found" in mod_wsgi/mod_python
+--------------------------------------------------------------------------------
+
+Bottle searches in ``./`` and ``./views/`` for templates. In a mod_python_ or mod_wsgi_ environment, the working directory (``./``) depends on your Apache settings. You should add an absolute path to the template search path::
+
+    bottle.TEMPLATE_PATH.insert(0,'/absolut/path/to/templates/')
+
+so bottle searches the right paths.
+
+Dynamic Routes and Slashes
+--------------------------------------------------------------------------------
+
+In :ref:`dynamic route syntax <tutorial-dynamic-routes>`, a placeholder token (``:name``) matches everything up to the next slash. This equals to ``[^/]+`` in regular expression syntax. To accept slashes too, you have to add a custom regular pattern to the placeholder. An example: ``/images/:filepath#.*#`` would match ``/images/icons/error.png`` but ``/images/:filename`` won't.
+
+Problems with reverse proxies
+--------------------------------------------------------------------------------
+
+Redirects and url-building only works if bottle knows the public address and location of your application. If you run bottle locally behind a reverse proxy or load balancer, some information might get lost along the way. For example, the ``wsgi.url_scheme`` value or the ``Host`` header might reflect the local request by your proxy, not the real request by the client. Here is a small WSGI middleware snippet that helps to fix these values::
+
+  def fix_environ_middleware(app):
+    def fixed_app(environ, start_response):
+      environ['wsgi.url_scheme'] = 'https'
+      environ['HTTP_X_FORWARDED_HOST'] = 'example.com'
+      return app(environ, start_response)
+    return https_app
+
+  app = bottle.default_app()    
+  app.wsgi = fix_environ_middleware(app.wsgi)
+  
+
+
+
+
+
+
diff --git a/html/_sources/index.txt b/html/_sources/index.txt
new file mode 100644 (file)
index 0000000..1bb081b
--- /dev/null
@@ -0,0 +1,112 @@
+.. highlight:: python
+.. currentmodule:: bottle
+
+.. _mako: http://www.makotemplates.org/
+.. _cheetah: http://www.cheetahtemplate.org/
+.. _jinja2: http://jinja.pocoo.org/2/
+.. _paste: http://pythonpaste.org/
+.. _fapws3: https://github.com/william-os4y/fapws3
+.. _bjoern: https://github.com/jonashaag/bjoern
+.. _flup: http://trac.saddi.com/flup
+.. _cherrypy: http://www.cherrypy.org/
+.. _WSGI: http://www.wsgi.org/wsgi/
+.. _Python: http://python.org/
+.. _testing: https://github.com/defnull/bottle/raw/master/bottle.py
+.. _issue_tracker: https://github.com/defnull/bottle/issues
+.. _PyPi: http://pypi.python.org/pypi/bottle
+
+============================
+Bottle: Python Web Framework
+============================
+
+Bottle is a fast, simple and lightweight WSGI_ micro web-framework for Python_. It is distributed as a single file module and has no dependencies other than the `Python Standard Library <http://docs.python.org/library/>`_. 
+
+
+* **Routing:** Requests to function-call mapping with support for clean and  dynamic URLs.
+* **Templates:** Fast and pythonic :ref:`built-in template engine <tutorial-templates>` and support for mako_, jinja2_ and cheetah_ templates.
+* **Utilities:** Convenient access to form data, file uploads, cookies, headers and other HTTP-related metadata.
+* **Server:** Built-in HTTP development server and support for paste_, fapws3_, bjoern_, `Google App Engine <http://code.google.com/intl/en-US/appengine/>`_, cherrypy_ or any other WSGI_ capable HTTP server.
+
+.. rubric:: Example: "Hello World" in a bottle
+
+::
+
+  from bottle import route, run, template
+
+  @route('/hello/:name')
+  def index(name='World'):
+      return template('<b>Hello {{name}}</b>!', name=name)
+
+  run(host='localhost', port=8080)
+
+Run this script or paste it into a Python console, then point your browser to `<http://localhost:8080/hello/world>`_. That's it.
+
+.. rubric:: Download and Install
+
+.. _download:
+
+.. __: https://github.com/defnull/bottle/raw/master/bottle.py
+
+Install the latest stable release via PyPi_ (``easy_install -U bottle``) or download `bottle.py`__ (unstable) into your project directory. There are no hard [1]_ dependencies other than the Python standard library. Bottle runs with **Python 2.5+ and 3.x**.
+
+User's Guide
+===============
+Start here if you want to learn how to use the bottle framework for web development. If you have any questions not answered here, feel free to ask the `mailing list <mailto:bottlepy@googlegroups.com>`_.
+
+.. toctree::
+   :maxdepth: 2
+
+   tutorial
+   routing
+   stpl
+   api
+   plugins/index
+
+
+Knowledge Base
+==============
+A collection of articles, guides and HOWTOs.
+
+.. toctree::
+   :maxdepth: 2
+
+   tutorial_app
+   async
+   recipes
+   faq
+
+
+Development and Contribution
+============================
+
+These chapters are intended for developers interested in the bottle development and release workflow.
+
+.. toctree::
+   :maxdepth: 2
+
+   changelog
+   development
+   plugindev
+
+
+.. toctree::
+   :hidden:
+
+   plugins/index
+   
+License
+==================
+
+Code and documentation are available according to the MIT License:
+
+.. include:: ../LICENSE
+  :literal:
+
+The Bottle logo however is *NOT* covered by that license. It is allowed to
+use the logo as a link to the bottle homepage or in direct context with
+the unmodified library. In all other cases please ask first.
+
+.. rubric:: Footnotes
+
+.. [1] Usage of the template or server adapter classes of course requires the corresponding template or server modules.
+
diff --git a/html/_sources/plugindev.txt b/html/_sources/plugindev.txt
new file mode 100644 (file)
index 0000000..40da98c
--- /dev/null
@@ -0,0 +1,240 @@
+.. module:: bottle
+
+
+========================
+Plugin Development Guide
+========================
+
+This guide explains the plugin API and how to write custom plugins. I suggest reading :ref:`plugins` first if you have not done that already. You might also want to have a look at the :doc:`/plugins/index` for some practical examples.
+
+.. note::
+
+    This is a draft. If you see any errors or find that a specific part is not explained clear enough, please tell the `mailing-list <mailto:bottlepy@googlegroups.com>`_ or file a `bug report <https://github.com/defnull/bottle/issues>`_.
+
+
+How Plugins Work: The Basics
+============================
+
+The plugin API builds on the concept of `decorators <http://docs.python.org/glossary.html#term-decorator>`_. To put it briefly, a plugin is a decorator applied to every single route callback of an application.
+
+Of course, this is just a simplification. Plugins can do a lot more than just decorating route callbacks, but it is a good starting point. Lets have a look at some code::
+
+    from bottle import response, install
+    import time
+
+    def stopwatch(callback):
+        def wrapper(*args, **kwargs):
+            start = time.time()
+            body = callback(*args, **kwargs)
+            end = time.time()
+            response.headers['X-Exec-Time'] = str(end - start)
+            return body
+        return wrapper
+
+    install(stopwatch)
+
+This plugin measures the execution time for each request and adds an appropriate ``X-Exec-Time`` header to the response. As you can see, the plugin returns a wrapper and the wrapper calls the original callback recursively. This is how decorators usually work.
+
+The last line tells Bottle to install the plugin to the default application. This causes the plugin to be automatically applied to all routes of that application. In other words, ``stopwatch()`` is called once for each route callback and the return value is used as a replacement for the original callback.
+
+Plugins are applied on demand, that is, as soon as a route is requested for the first time. For this to work properly in multi-threaded environments, the plugin should be thread-safe. This is not a problem most of the time, but keep it in mind.
+
+Once all plugins are applied to a route, the wrapped callback is cached and subsequent requests are handled by the cached version directly. This means that a plugin is usually applied only once to a specific route. That cache, however, is cleared every time the list of installed plugins changes. Your plugin should be able to decorate the same route more than once.
+
+The decorator API is quite limited, though. You don't know anything about the route being decorated or the associated application object and have no way to efficiently store data that is shared among all routes. But fear not! Plugins are not limited to just decorator functions. Bottle accepts anything as a plugin as long as it is callable or implements an extended API. This API is described below and gives you a lot of control over the whole process.
+
+
+Plugin API
+==========
+
+:class:`Plugin` is not a real class (you cannot import it from :mod:`bottle`) but an interface that plugins are expected to implement. Bottle accepts any object of any type as a plugin, as long as it conforms to the following API.
+
+.. class:: Plugin(object)
+
+    Plugins must be callable or implement :meth:`apply`. If :meth:`apply` is defined, it is always preferred over calling the plugin directly. All other methods and attributes are optional.
+
+    .. attribute:: name
+
+        Both :meth:`Bottle.uninstall` and the `skip` parameter of :meth:`Bottle.route()` accept a name string to refer to a plugin or plugin type. This works only for plugins that have a name attribute.
+
+    .. attribute:: api
+
+        The Plugin API is still evolving. This integer attribute tells bottle which version to use. If it is missing, bottle defaults to the first version. The current version is ``2``. See :ref:`plugin-changelog` for details.
+
+    .. method:: setup(self, app)
+
+        Called as soon as the plugin is installed to an application (see :meth:`Bottle.install`). The only parameter is the associated application object.
+
+    .. method:: __call__(self, callback)
+
+        As long as :meth:`apply` is not defined, the plugin itself is used as a decorator and applied directly to each route callback. The only parameter is the callback to decorate. Whatever is returned by this method replaces the original callback. If there is no need to wrap or replace a given callback, just return the unmodified callback parameter.
+
+    .. method:: apply(self, callback, route)
+
+        If defined, this method is used in favor of :meth:`__call__` to decorate route callbacks. The additional `route` parameter is an instance of :class:`Route` and provides a lot of meta-information and context for that route. See :ref:`route-context` for details.
+
+    .. method:: close(self)
+
+        Called immediately before the plugin is uninstalled or the application is closed (see :meth:`Bottle.uninstall` or :meth:`Bottle.close`).
+
+
+Both :meth:`Plugin.setup` and :meth:`Plugin.close` are *not* called for plugins that are applied directly to a route via the :meth:`Bottle.route()` decorator, but only for plugins installed to an application.
+
+
+.. _plugin-changelog:
+
+Plugin API changes
+------------------
+
+The Plugin API is still evolving and changed with Bottle 0.10 to address certain issues with the route context dictionary. To ensure backwards compatibility with 0.9 Plugins, we added an optional :attr:`Plugin.api` attribute to tell bottle which API to use. The API differences are summarized here.
+
+* **Bottle 0.9 API 1** (:attr:`Plugin.api` not present)
+
+  * Original Plugin API as described in the 0.9 docs.
+
+* **Bottle 0.10 API 2** (:attr:`Plugin.api` equals 2)
+
+  * The `context` parameter of the :meth:`Plugin.apply` method is now an instance of :class:`Route` instead of a context dictionary.
+
+.. _route-context:
+
+
+The Route Context
+=================
+
+The :class:`Route` instance passed to :meth:`Plugin.apply` provides detailed informations about the associated route. The most important attributes are summarized here:
+
+===========  =================================================================
+Attribute    Description
+===========  =================================================================
+app          The application object this route is installed to.
+rule         The rule string (e.g. ``/wiki/:page``).
+method       The HTTP method as a string (e.g. ``GET``).
+callback     The original callback with no plugins applied. Useful for
+             introspection.
+name         The name of the route (if specified) or ``None``.
+plugins      A list of route-specific plugins. These are applied in addition to
+             application-wide plugins. (see :meth:`Bottle.route`).
+skiplist     A list of plugins to not apply to this route (again, see
+             :meth:`Bottle.route`).
+config       Additional keyword arguments passed to the :meth:`Bottle.route`
+             decorator are stored in this dictionary. Used for route-specific
+             configuration and meta-data.
+===========  =================================================================
+
+For your plugin, :attr:`Route.config` is probably the most important attribute. Keep in mind that this dictionary is local to the route, but shared between all plugins. It is always a good idea to add a unique prefix or, if your plugin needs a lot of configuration, store it in a separate namespace within the `config` dictionary. This helps to avoid naming collisions between plugins.
+
+
+Changing the :class:`Route` object
+----------------------------------
+
+While some :class:`Route` attributes are mutable, changes may have unwanted effects on other plugins. It is most likely a bad idea to monkey-patch a broken route instead of providing a helpful error message and let the user fix the problem.
+
+In some rare cases, however, it might be justifiable to break this rule. After you made your changes to the :class:`Route` instance, raise :exc:`RouteReset` as an exception. This removes the current route from the cache and causes all plugins to be re-applied. The router is not updated, however. Changes to `rule` or `method` values have no effect on the router, but only on plugins. This may change in the future, though.
+
+
+Runtime optimizations
+=====================
+
+Once all plugins are applied to a route, the wrapped route callback is cached to speed up subsequent requests. If the behavior of your plugin depends on configuration, and you want to be able to change that configuration at runtime, you need to read the configuration on each request. Easy enough.
+
+For performance reasons, however, it might be worthwhile to choose a different wrapper based on current needs, work with closures, or enable or disable a plugin at runtime. Let's take the built-in HooksPlugin as an example: If no hooks are installed, the plugin removes itself from all affected routes and has virtaully no overhead. As soon as you install the first hook, the plugin activates itself and takes effect again.
+
+To achieve this, you need control over the callback cache: :meth:`Route.reset` clears the cache for a single route and :meth:`Bottle.reset` clears all caches for all routes of an application at once. On the next request, all plugins are re-applied to the route as if it were requested for the first time.
+
+Both methods won't affect the current request if called from within a route callback, of cause. To force a restart of the current request, raise :exc:`RouteReset` as an exception.
+
+
+Plugin Example: SQLitePlugin
+============================
+
+This plugin provides an sqlite3 database connection handle as an additional keyword argument to wrapped callbacks, but only if the callback expects it. If not, the route is ignored and no overhead is added. The wrapper does not affect the return value, but handles plugin-related exceptions properly. :meth:`Plugin.setup` is used to inspect the application and search for conflicting plugins.
+
+::
+
+    import sqlite3
+    import inspect
+
+    class SQLitePlugin(object):
+        ''' This plugin passes an sqlite3 database handle to route callbacks
+        that accept a `db` keyword argument. If a callback does not expect
+        such a parameter, no connection is made. You can override the database
+        settings on a per-route basis. '''
+
+        name = 'sqlite'
+        api = 2
+
+        def __init__(self, dbfile=':memory:', autocommit=True, dictrows=True,
+                     keyword='db'):
+             self.dbfile = dbfile
+             self.autocommit = autocommit
+             self.dictrows = dictrows
+             self.keyword = keyword
+
+        def setup(self, app):
+            ''' Make sure that other installed plugins don't affect the same
+                keyword argument.'''
+            for other in app.plugins:
+                if not isinstance(other, SQLitePlugin): continue
+                if other.keyword == self.keyword:
+                    raise PluginError("Found another sqlite plugin with "\
+                    "conflicting settings (non-unique keyword).")
+
+        def apply(self, callback, context):
+            # Override global configuration with route-specific values.
+            conf = context.config.get('sqlite') or {}
+            dbfile = conf.get('dbfile', self.dbfile)
+            autocommit = conf.get('autocommit', self.autocommit)
+            dictrows = conf.get('dictrows', self.dictrows)
+            keyword = conf.get('keyword', self.keyword)
+
+            # Test if the original callback accepts a 'db' keyword.
+            # Ignore it if it does not need a database handle.
+            args = inspect.getargspec(context.callback)[0]
+            if keyword not in args:
+                return callback
+
+            def wrapper(*args, **kwargs):
+                # Connect to the database
+                db = sqlite3.connect(dbfile)
+                # This enables column access by name: row['column_name']
+                if dictrows: db.row_factory = sqlite3.Row
+                # Add the connection handle as a keyword argument.
+                kwargs[keyword] = db
+
+                try:
+                    rv = callback(*args, **kwargs)
+                    if autocommit: db.commit()
+                except sqlite3.IntegrityError, e:
+                    db.rollback()
+                    raise HTTPError(500, "Database Error", e)
+                finally:
+                    db.close()
+                return rv
+
+            # Replace the route callback with the wrapped one.
+            return wrapper
+
+This plugin is actually useful and very similar to the version bundled with Bottle. Not bad for less than 60 lines of code, don't you think? Here is a usage example::
+
+    sqlite = SQLitePlugin(dbfile='/tmp/test.db')
+    bottle.install(sqlite)
+
+    @route('/show/:page')
+    def show(page, db):
+        row = db.execute('SELECT * from pages where name=?', page).fetchone()
+        if row:
+            return template('showpage', page=row)
+        return HTTPError(404, "Page not found")
+
+    @route('/static/:fname#.*#')
+    def static(fname):
+        return static_file(fname, root='/some/path')
+
+    @route('/admin/set/:db#[a-zA-Z]+#', skip=[sqlite])
+    def change_dbfile(db):
+        sqlite.dbfile = '/tmp/%s.db' % db
+        return "Switched DB to %s.db" % db
+
+The first route needs a database connection and tells the plugin to create a handle by requesting a ``db`` keyword argument. The second route does not need a database and is therefore ignored by the plugin. The third route does expect a 'db' keyword argument, but explicitly skips the sqlite plugin. This way the argument is not overruled by the plugin and still contains the value of the same-named url argument.
+
diff --git a/html/_sources/plugins/index.txt b/html/_sources/plugins/index.txt
new file mode 100644 (file)
index 0000000..8130f2f
--- /dev/null
@@ -0,0 +1,59 @@
+.. module:: bottle
+
+=========================
+List of available Plugins
+=========================
+
+This is a list of third-party plugins that add extend Bottles core functionality or integrate other libraries with the Bottle framework.
+
+Have a look at :ref:`plugins` for general questions about plugins (installation, usage). If you plan to develop a new plugin, the :doc:`/plugindev` may help you.
+
+`Bottle-Cork <http://cork.firelet.net/>`_
+       Cork provides a simple set of methods to implement Authentication and Authorization in web applications based on Bottle.
+
+`Bottle-Extras <http://pypi.python.org/pypi/bottle-extras/>`_
+       Meta package to install the bottle plugin collection.
+
+`Bottle-Flash <http://pypi.python.org/pypi/bottle-flash/>`_
+       flash plugin for bottle
+
+`Bottle-Hotqueue <http://pypi.python.org/pypi/bottle-hotqueue/>`_
+       FIFO Queue for Bottle built upon redis
+
+`Macaron <http://nobrin.github.com/macaron/webapp.html>`_
+       Macaron is an object-relational mapper (ORM) for SQLite.
+
+`Bottle-Memcache <http://pypi.python.org/pypi/bottle-memcache/>`_
+       Memcache integration for Bottle.
+
+`Bottle-MongoDB <http://pypi.python.org/pypi/bottle-mongodb/>`_
+       MongoDB integration for Bottle
+
+`Bottle-Redis <http://pypi.python.org/pypi/bottle-redis/>`_
+       Redis integration for Bottle.
+
+`Bottle-Renderer <http://pypi.python.org/pypi/bottle-renderer/>`_
+       Renderer plugin for bottle
+
+`Bottle-Servefiles <http://pypi.python.org/pypi/bottle-servefiles/>`_
+       A reusable app that serves static files for bottle apps
+
+`Bottle-Sqlalchemy <http://pypi.python.org/pypi/bottle-sqlalchemy/>`_
+       SQLAlchemy integration for Bottle.
+
+`Bottle-Sqlite <http://pypi.python.org/pypi/bottle-sqlite/>`_
+       SQLite3 database integration for Bottle.
+
+`Bottle-Web2pydal <http://pypi.python.org/pypi/bottle-web2pydal/>`_
+       Web2py Dal integration for Bottle.
+
+`Bottle-Werkzeug <http://pypi.python.org/pypi/bottle-werkzeug/>`_
+       Integrates the `werkzeug` library (alternative request and response objects, advanced debugging middleware and more).
+
+Plugins listed here are not part of Bottle or the Bottle project, but developed and maintained by third parties.
+
+.. toctree::
+    :glob:
+    :hidden:
+    
+    /plugins/*
diff --git a/html/_sources/plugins/sqlite.txt b/html/_sources/plugins/sqlite.txt
new file mode 100644 (file)
index 0000000..d4f2891
--- /dev/null
@@ -0,0 +1 @@
+.. include:: ../../plugins/sqlite/README
diff --git a/html/_sources/plugins/werkzeug.txt b/html/_sources/plugins/werkzeug.txt
new file mode 100644 (file)
index 0000000..f611fca
--- /dev/null
@@ -0,0 +1 @@
+.. include:: ../../plugins/werkzeug/README
diff --git a/html/_sources/recipes.txt b/html/_sources/recipes.txt
new file mode 100644 (file)
index 0000000..0ea2d38
--- /dev/null
@@ -0,0 +1,257 @@
+.. module:: bottle
+
+.. _beaker: http://beaker.groovie.org/
+.. _mod_python: http://www.modpython.org/
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
+.. _werkzeug: http://werkzeug.pocoo.org/documentation/dev/debug.html
+.. _paste: http://pythonpaste.org/modules/evalexception.html
+.. _pylons: http://pylonshq.com/
+.. _gevent: http://www.gevent.org/
+.. _compression: https://github.com/defnull/bottle/issues/92
+.. _GzipFilter: http://www.cherrypy.org/wiki/GzipFilter
+.. _cherrypy: http://www.cherrypy.org
+.. _heroku: http://heroku.com
+
+Recipes
+=============
+
+This is a collection of code snippets and examples for common use cases. 
+
+Keeping track of Sessions
+----------------------------
+
+There is no built-in support for sessions because there is no *right* way to do it (in a micro framework). Depending on requirements and environment you could use beaker_ middleware with a fitting backend or implement it yourself. Here is an example for beaker sessions with a file-based backend::
+
+    import bottle
+    from beaker.middleware import SessionMiddleware
+
+    session_opts = {
+        'session.type': 'file',
+        'session.cookie_expires': 300,
+        'session.data_dir': './data',
+        'session.auto': True
+    }
+    app = SessionMiddleware(bottle.app(), session_opts)
+
+    @bottle.route('/test')
+    def test():
+      s = bottle.request.environ.get('beaker.session')
+      s['test'] = s.get('test',0) + 1
+      s.save()
+      return 'Test counter: %d' % s['test']
+
+    bottle.run(app=app)
+
+Debugging with Style: Debugging Middleware
+--------------------------------------------------------------------------------
+
+Bottle catches all Exceptions raised in your app code to prevent your WSGI server from crashing. If the built-in :func:`debug` mode is not enough and you need exceptions to propagate to a debugging middleware, you can turn off this behaviour::
+
+    import bottle
+    app = bottle.app() 
+    app.catchall = False #Now most exceptions are re-raised within bottle.
+    myapp = DebuggingMiddleware(app) #Replace this with a middleware of your choice (see below)
+    bottle.run(app=myapp)
+
+Now, bottle only catches its own exceptions (:exc:`HTTPError`, :exc:`HTTPResponse` and :exc:`BottleException`) and your middleware can handle the rest.
+
+The werkzeug_ and paste_ libraries both ship with very powerful debugging WSGI middleware. Look at :class:`werkzeug.debug.DebuggedApplication` for werkzeug_ and :class:`paste.evalexception.middleware.EvalException` for paste_. They both allow you do inspect the stack and even execute python code within the stack context, so **do not use them in production**.
+
+
+Unit-Testing Bottle Applications
+--------------------------------------------------------------------------------
+
+Unit-testing is usually performed against methods defined in your web application without running a WSGI environment.
+
+A simple example using `Nose <http://readthedocs.org/docs/nose>`_::
+
+    import bottle
+    
+    @bottle.route('/')
+    def index():
+        return 'Hi!'
+
+    if __name__ == '__main__':
+        bottle.run()
+
+Test script::
+
+    import mywebapp
+    
+    def test_webapp_index():
+        assert mywebapp.index() == 'Hi!'
+
+In the example the Bottle route() method is never executed - only index() is tested.
+
+
+Functional Testing Bottle Applications
+--------------------------------------------------------------------------------
+
+Any HTTP-based testing system can be used with a running WSGI server, but some testing frameworks work more intimately with WSGI, and provide the ability the call WSGI applications in a controlled environment, with tracebacks and full use of debugging tools. `Testing tools for WSGI <http://www.wsgi.org/en/latest/testing.html>`_ is a good starting point.
+
+Example using `WebTest <http://webtest.pythonpaste.org/>`_ and `Nose <http://readthedocs.org/docs/nose>`_::
+
+    from webtest import TestApp
+    import mywebapp
+
+    def test_functional_login_logout():
+        app = TestApp(mywebapp.app)
+        
+        app.post('/login', {'user': 'foo', 'pass': 'bar'}) # log in and get a cookie
+
+        assert app.get('/admin').status == '200 OK'        # fetch a page successfully
+
+        app.get('/logout')                                 # log out
+        app.reset()                                        # drop the cookie
+
+        # fetch the same page, unsuccessfully
+        assert app.get('/admin').status == '401 Unauthorized'
+
+
+Embedding other WSGI Apps
+--------------------------------------------------------------------------------
+
+This is not the recommend way (you should use a middleware in front of bottle to do this) but you can call other WSGI applications from within your bottle app and let bottle act as a pseudo-middleware. Here is an example::
+
+    from bottle import request, response, route
+    subproject = SomeWSGIApplication()
+
+    @route('/subproject/:subpath#.*#', method='ALL')
+    def call_wsgi(subpath):
+        new_environ = request.environ.copy()
+        new_environ['SCRIPT_NAME'] = new_environ.get('SCRIPT_NAME','') + '/subproject'
+        new_environ['PATH_INFO'] = '/' + subpath
+        def start_response(status, headerlist):
+            response.status = int(status.split()[0])
+            for key, value in headerlist:
+                response.add_header(key, value)
+        return app(new_environ, start_response)
+
+Again, this is not the recommend way to implement subprojects. It is only here because many people asked for this and to show how bottle maps to WSGI.
+
+
+Ignore trailing slashes
+--------------------------------------------------------------------------------
+
+For Bottle, ``/example`` and ``/example/`` are two different routes [1]_. To treat both URLs the same you can add two ``@route`` decorators::
+
+    @route('/test')
+    @route('/test/')
+    def test(): return 'Slash? no?'
+
+or add a WSGI middleware that strips trailing slashes from all URLs::
+
+    class StripPathMiddleware(object):
+      def __init__(self, app):
+        self.app = app
+      def __call__(self, e, h):
+        e['PATH_INFO'] = e['PATH_INFO'].rstrip('/')
+        return self.app(e,h)
+    
+    app = bottle.app()
+    myapp = StripPathMiddleware(app)
+    bottle.run(app=myapp)
+
+.. rubric:: Footnotes
+
+.. [1] Because they are. See <http://www.ietf.org/rfc/rfc3986.txt>
+
+
+Keep-alive requests
+-------------------
+
+.. note::
+
+    For a more detailed explanation, see :doc:`async`.
+
+Several "push" mechanisms like XHR multipart need the ability to write response data without closing the connection in conjunction with the response header "Connection: keep-alive". WSGI does not easily lend itself to this behavior, but it is still possible to do so in Bottle by using the gevent_ async framework. Here is a sample that works with either the gevent_ HTTP server or the paste_ HTTP server (it may work with others, but I have not tried). Just change ``server='gevent'`` to ``server='paste'`` to use the paste_ server::
+
+    from gevent import monkey; monkey.patch_all()
+
+    import time
+    from bottle import route, run
+    
+    @route('/stream')
+    def stream():
+        yield 'START'
+        time.sleep(3)
+        yield 'MIDDLE'
+        time.sleep(5)
+        yield 'END'
+    
+    run(host='0.0.0.0', port=8080, server='gevent')
+
+If you browse to ``http://localhost:8080/stream``, you should see 'START', 'MIDDLE', and 'END' show up one at a time (rather than waiting 8 seconds to see them all at once).
+
+Gzip Compression in Bottle
+--------------------------
+
+.. note::
+   For a detailed discussion, see compression_
+
+A common feature request is for Bottle to support Gzip compression, which speeds up sites by compressing static resources (like CSS and JS files) during a request.
+
+Supporting Gzip compression is not a straightforward proposition, due to a number of corner cases that crop up frequently. A proper Gzip implementation must:
+
+* Compress on the fly and be fast doing so.
+* Do not compress for browsers that don't support it.
+* Do not compress files that are compressed already (images, videos).
+* Do not compress dynamic files.
+* Support two differed compression algorithms (gzip and deflate).
+* Cache compressed files that don't change often.
+* De-validate the cache if one of the files changed anyway.
+* Make sure the cache does not get to big.
+* Do not cache small files because a disk seek would take longer than on-the-fly compression.
+
+Because of these requirements, it is the recommendation of the Bottle project that Gzip compression is best handled by the WSGI server Bottle runs on top of. WSGI servers such as cherrypy_ provide a GzipFilter_ middleware that can be used to accomplish this.
+
+
+Using the hooks plugin
+----------------------
+
+For example, if you want to allow Cross-Origin Resource Sharing for
+the content returned by all of your URL, you can use the hook
+decorator and setup a callback function::
+
+    from bottle import hook, response, route
+
+    @hook('after_request')
+    def enable_cors():
+        response.headers['Access-Control-Allow-Origin'] = '*'
+
+    @route('/foo')
+    def say_foo():
+        return 'foo!'
+
+    @route('/bar')
+    def say_bar():
+        return {'type': 'friendly', 'content': 'Hi!'}
+
+You can also use the ``before_callback`` to take an action before
+every function gets called.
+
+
+Using Bottle with Heroku
+------------------------
+
+Heroku_, a popular cloud application platform now provides support
+for running Python applications on their infastructure. 
+
+This recipe is based upon the `Heroku Quickstart 
+<http://devcenter.heroku.com/articles/quickstart>`_, 
+with Bottle specific code replacing the 
+`Write Your App <http://devcenter.heroku.com/articles/python#write_your_app>`_ 
+section of the `Getting Started with Python on Heroku/Cedar 
+<http://devcenter.heroku.com/articles/python>`_ guide::
+
+    import os
+    from bottle import route, run
+
+    @route("/")
+    def hello_world():
+            return "Hello World!"
+
+    run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))
+
+Heroku's app stack passes the port that the application needs to
+listen on for requests, using the `os.environ` dictionary.
diff --git a/html/_sources/routing.txt b/html/_sources/routing.txt
new file mode 100644 (file)
index 0000000..fe89621
--- /dev/null
@@ -0,0 +1,129 @@
+================================================================================
+Request Routing
+================================================================================
+
+Bottle uses a powerful routing engine to find the right callback for each request. The :ref:`tutorial <tutorial-routing>` shows you the basics. This document covers advanced techniques and rule mechanics in detail.
+
+Rule Syntax
+--------------------------------------------------------------------------------
+
+The :class:`Router` distinguishes between two basic types of routes: **static routes** (e.g. ``/contact``) and **dynamic routes** (e.g. ``/hello/<name>``). A route that contains one or more *wildcards* it is considered dynamic. All other routes are static.
+
+.. versionchanged:: 0.10
+
+The simplest form of a wildcard consists of a name enclosed in angle brackets (e.g. ``<name>``). The name should be unique for a given route and form a valid python identifier (alphanumeric, starting with a letter). This is because wildcards are used as keyword arguments for the request callback later.
+
+Each wildcard matches one or more characters, but stops at the first slash (``/``). This equals a regular expression of ``[^/]+`` and ensures that only one path segment is matched and routes with more than one wildcard stay unambiguous.
+
+The rule ``/<action>/<item>`` matches as follows:
+
+============ =========================================
+Path         Result
+============ =========================================
+/save/123    ``{'action': 'save', 'item': '123'}``
+/save/123/   `No Match`
+/save/       `No Match`
+//123        `No Match`
+============ =========================================
+
+You can change the exact behaviour in many ways using filters. This is described in the next section.
+
+Wildcard Filters
+--------------------------------------------------------------------------------
+
+.. versionadded:: 0.10
+
+Filters are used to define more specific wildcards, and/or transform the matched part of the URL before it is passed to the callback. A filtered wildcard is declared as ``<name:filter>`` or ``<name:filter:config>``. The syntax for the optional config part depends on the filter used.
+
+The following standard filters are implemented:
+
+* **:int** matches (signed) digits and converts the value to integer.
+* **:float** similar to :int but for decimal numbers.
+* **:path** matches all characters including the slash character in a non-greedy way and may be used to match more than one path segment.
+* **:re[:exp]** allows you to specify a custom regular expression in the config field. The matched value is not modified.
+
+You can add your own filters to the router. All you need is a function that returns three elements: A regular expression string, a callable to convert the URL fragment to a python value, and a callable that does the opposite. The filter function is called with the configuration string as the only parameter and may parse it as needed::
+
+    app = Bottle()
+
+    def list_filter(config):
+        ''' Matches a comma separated list of numbers. '''
+        delimiter = config or ','
+        regexp = r'\d+(%s\d)*' % re.escape(delimiter)
+
+        def to_python(match):
+            return map(int, match.split(delimiter))
+        
+        def to_url(numbers):
+            return delimiter.join(map(str, numbers))
+        
+        return regexp, to_python, to_url
+
+    app.router.add_filter('list', list_filter)
+
+    @app.route('/follow/<ids:list>')
+    def follow_users(ids):
+        for id in ids:
+            ...
+
+
+Legacy Syntax
+--------------------------------------------------------------------------------
+
+.. versionchanged:: 0.10
+
+The new rule syntax was introduce in **Bottle 0.10** to simplify some common use cases, but the old syntax still works and you can find lot code examples still using it. The differences are best described by example:
+
+=================== ====================
+Old Syntax          New Syntax
+=================== ====================
+``:name``           ``<name>``
+``:name#regexp#``   ``<name:re:regexp>``
+``:#regexp#``       ``<:re:regexp>``
+``:##``             ``<:re>``
+=================== ====================
+
+Try to avoid the old syntax in future projects if you can. It is not currently deprecated, but will be eventually.
+
+
+Routing Order
+--------------------------------------------------------------------------------
+
+With the power of wildcards and regular expressions it is possible to define overlapping routes. If multiple routes match the same URL, things get a bit tricky. To fully understand what happens in this case, you need to know in which order routes are checked by the router.
+
+First you should know that routes are grouped by their path rule. Two routes with the same path rule but different methods are grouped together and the first route determines the position of both routes. Fully identical routes (same path rule and method) replace previously defined routes, but keep the position of their predecessor.
+
+Static routes are checked first. This is mostly for performance reasons and can be switched off, but is currently the default. If no static route matches the request, the dynamic routes are checked in the order they were defined. The first hit ends the search. If no rule matched, a "404 Page not found" error is returned.
+
+In a second step, the request method is checked. If no exact match is found, and the request method is HEAD, the router checks for a GET route. Otherwise, it checks for an ANY route. If that fails too, a "405 Method not allowed" error is returned.
+
+Here is an example where this might bite you::
+
+    @route('/<action>/<name>', method='GET')
+    @route('/save/<name>', method='POST')
+
+The second route will never hit. Even POST requests don't arrive at the second route because the request method is checked in a separate step. The router stops at the first route which matches the request path, then checks for a valid request method, can't find one and raises a 405 error.
+
+Sounds complicated, and it is. That is the price for performance. It is best to avoid ambiguous routes at all and choose unique prefixes for each route. This implementation detail may change in the future, though. We are working on it.
+
+
+Explicit routing configuration
+--------------------------------------------------------------------------------
+
+Route decorator can also be directly called as method. This way provides flexibility in complex setups, allowing you to directly control, when and how routing configuration done.
+
+Here is a basic example of explicit routing configuration for default bottle application::
+
+    def setup_routing():
+        bottle.route('/', method='GET', index)
+        bottle.route('/edit', method=['GET', 'POST'], edit)
+
+In fact, any :class:`Bottle` instance routing can be configured same way::
+
+    def setup_routing(app):
+        app.route('/new', method=['GET', 'POST'], form_new)
+        app.route('/edit', method=['GET', 'POST'], form_edit)
+
+    app = Bottle()
+    setup_routing(app)
+
diff --git a/html/_sources/stpl.txt b/html/_sources/stpl.txt
new file mode 100644 (file)
index 0000000..10c7699
--- /dev/null
@@ -0,0 +1,231 @@
+======================
+SimpleTemplate Engine
+======================
+
+.. currentmodule:: bottle
+
+Bottle comes with a fast, powerful and easy to learn built-in template engine called *SimpleTemplate* or *stpl* for short. It is the default engine used by the :func:`view` and :func:`template` helpers but can be used as a stand-alone general purpose template engine too. This document explains the template syntax and shows examples for common use cases.
+
+.. rubric:: Basic API Usage:
+
+:class:`SimpleTemplate` implements the :class:`BaseTemplate` API::
+
+   >>> from bottle import SimpleTemplate
+   >>> tpl = SimpleTemplate('Hello {{name}}!')
+   >>> tpl.render(name='World')
+   u'Hello World!'
+
+In this document we use the :func:`template` helper in examples for the sake of simplicity::
+
+   >>> from bottle import template
+   >>> template('Hello {{name}}!', name='World')
+   u'Hello World!'
+
+Just keep in mind that compiling and rendering templates are two different actions, even if the :func:`template` helper hides this fact. Templates are usually compiled only once and cached internally, but rendered many times with different keyword arguments.
+
+:class:`SimpleTemplate` Syntax
+==============================
+
+Python is a very powerful language but its whitespace-aware syntax makes it difficult to use as a template language. SimpleTemplate removes some of these restrictions and allows you to write clean, readable and maintainable templates while preserving full access to the features, libraries and speed of the Python language.
+
+.. warning::
+
+   The :class:`SimpleTemplate` syntax compiles directly to python bytecode and is executed on each :meth:`SimpleTemplate.render` call. Do not render untrusted templates! They may contain and execute harmful python code.
+
+Inline Expressions
+-----------------
+
+You already learned the use of the ``{{...}}`` syntax from the "Hello World!" example above, but there is more: any python expression is allowed within the curly brackets as long as it returns a string or something that has a string representation::
+
+  >>> template('Hello {{name}}!', name='World')
+  u'Hello World!'
+  >>> template('Hello {{name.title() if name else "stranger"}}!', name=None)
+  u'Hello stranger!'
+  >>> template('Hello {{name.title() if name else "stranger"}}!', name='mArC')
+  u'Hello Marc!'
+
+The contained python expression is executed at render-time and has access to all keyword arguments passed to the :meth:`SimpleTemplate.render` method. HTML special characters are escaped automatically to prevent `XSS <http://en.wikipedia.org/wiki/Cross-Site_Scripting>`_ attacks. You can start the expression with an exclamation mark to disable escaping for that expression::
+
+  >>> template('Hello {{name}}!', name='<b>World</b>')
+  u'Hello &lt;b&gt;World&lt;/b&gt;!'
+  >>> template('Hello {{!name}}!', name='<b>World</b>')
+  u'Hello <b>World</b>!'
+
+.. highlight:: html+django
+
+Embedded python code
+--------------------
+
+The ``%`` character marks a line of python code. The only difference between this and real python code is that you have to explicitly close blocks with an ``%end`` statement. In return you can align the code with the surrounding template and don't have to worry about correct indentation of blocks. The *SimpleTemplate* parser handles that for you. Lines *not* starting with a ``%`` are rendered as text as usual::
+
+  %if name:
+    Hi <b>{{name}}</b>
+  %else:
+    <i>Hello stranger</i>
+  %end
+
+The ``%`` character is only recognised if it is the first non-whitespace character in a line. To escape a leading ``%`` you can add a second one. ``%%`` is replaced by a single ``%`` in the resulting template::
+
+  This line contains a % but no python code.
+  %% This text-line starts with '%'
+  %%% This text-line starts with '%%'
+
+Suppressing line breaks
+-----------------------
+
+You can suppress the line break in front of a code-line by adding a double backslash at the end of the line::
+
+  <span>\\
+  %if True:
+  nobreak\\
+  %end
+  </span>
+
+This template produces the following output::
+
+  <span>nobreak</span>
+
+The ``%include`` Statement
+--------------------------
+
+You can include other templates using the ``%include sub_template [kwargs]`` statement. The ``sub_template`` parameter specifies the name or path of the template to be included. The rest of the line is interpreted as a comma-separated list of ``key=statement`` pairs similar to keyword arguments in function calls. They are passed to the sub-template analogous to a :meth:`SimpleTemplate.render` call. The ``**kwargs`` syntax for passing a dict is allowed too::
+
+  %include header_template title='Hello World'
+  <p>Hello World</p>
+  %include footer_template
+
+The ``%rebase`` Statement
+-------------------------
+
+The ``%rebase base_template [kwargs]`` statement causes ``base_template`` to be rendered instead of the original template. The base-template then includes the original template using an empty ``%include`` statement and has access to all variables specified by ``kwargs``. This way it is possible to wrap a template with another template or to simulate the inheritance feature found in some other template engines.
+
+Let's say you have a content template and want to wrap it with a common HTML layout frame. Instead of including several header and footer templates, you can use a single base-template to render the layout frame.
+
+Base-template named ``layout.tpl``::
+
+  <html>
+  <head>
+    <title>{{title or 'No title'}}</title>
+  </head>
+  <body>
+    %include
+  </body>
+  </html>
+
+Main-template named ``content.tpl``::
+
+  This is the page content: {{content}}
+  %rebase layout title='Content Title'
+
+Now you can render ``content.tpl``:
+
+.. code-block:: python
+
+  >>> print template('content', content='Hello World!')
+
+.. code-block:: html
+
+  <html>
+  <head>
+    <title>Content Title</title>
+  </head>
+  <body>
+    This is the page content: Hello World!
+  </body>
+  </html>
+
+A more complex scenario involves chained rebases and multiple content blocks. The ``block_content.tpl`` template defines two functions and passes them to a ``columns.tpl`` base template::
+
+  %def leftblock():
+    Left block content.
+  %end
+  %def rightblock():
+    Right block content.
+  %end
+  %rebase columns leftblock=leftblock, rightblock=rightblock, title=title
+
+The ``columns.tpl`` base-template uses the two callables to render the content of the left and right column. It then wraps itself with the ``layout.tpl`` template defined earlier::
+
+  %rebase layout title=title
+  <div style="width: 50%; float:left">
+    %leftblock()
+  </div>
+  <div style="width: 50%; float:right">
+    %rightblock()
+  </div>
+
+Lets see how ``block_content.tpl`` renders:
+
+.. code-block:: python
+
+  >>> print template('block_content', title='Hello World!')
+
+.. code-block:: html
+
+  <html>
+  <head>
+    <title>Hello World</title>
+  </head>
+  <body>
+  <div style="width: 50%; float:left">
+    Left block content.
+  </div>
+  <div style="width: 50%; float:right">
+    Right block content.
+  </div>
+  </body>
+  </html>
+
+Namespace Functions
+-------------------
+
+Accessing undefined variables in a template raises :exc:`NameError` and
+stops rendering immediately. This is standard python behavior and nothing new,
+but vanilla python lacks an easy way to check the availability of a variable.
+This quickly gets annoying if you want to support flexible inputs or use the
+same template in different situations. SimpleTemplate helps you out here: The
+following three functions are defined in the default namespace and accessible
+from anywhere within a template:
+
+.. currentmodule:: stpl
+
+.. function:: defined(name)
+
+    Return True if the variable is defined in the current template namespace,
+    False otherwise.
+
+.. function:: get(name, default=None)
+
+    Return the variable, or a default value.
+
+.. function:: setdefault(name, default)
+
+    If the variable is not defined, create it with the given default value.
+    Return the variable.
+
+Here is an example that uses all three functions to implement optional template
+variables in different ways::
+
+    % setdefault('text', 'No Text')
+    <h1>{{get('title', 'No Title')}}</h1>
+    <p> {{ text }} </p>
+    % if defined('author'):
+      <p>By {{ author }}</p>
+    % end
+
+.. currentmodule:: bottle
+
+
+:class:`SimpleTemplate` API
+==============================
+
+.. autoclass:: SimpleTemplate
+   :members:
+
+Known bugs
+==============================
+
+Some syntax constructions allowed in python are problematic within a template. The following syntaxes won't work with SimpleTemplate:
+
+  * Multi-line statements must end with a backslash (``\``) and a comment, if present, must not contain any additional ``#`` characters.
+  * Multi-line strings are not supported yet.
diff --git a/html/_sources/tutorial.txt b/html/_sources/tutorial.txt
new file mode 100644 (file)
index 0000000..9ef531d
--- /dev/null
@@ -0,0 +1,968 @@
+.. module:: bottle
+
+.. _Apache Server:
+.. _Apache: http://www.apache.org/
+.. _cherrypy: http://www.cherrypy.org/
+.. _decorator: http://docs.python.org/glossary.html#term-decorator
+.. _flup: http://trac.saddi.com/flup
+.. _http_code: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+.. _http_method: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
+.. _json: http://de.wikipedia.org/wiki/JavaScript_Object_Notation
+.. _lighttpd: http://www.lighttpd.net/
+.. _mako: http://www.makotemplates.org/
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
+.. _Paste: http://pythonpaste.org/
+.. _Pound: http://www.apsis.ch/pound/
+.. _`WSGI Specification`: http://www.wsgi.org/wsgi/
+.. _issue: http://github.com/defnull/bottle/issues
+.. _Python: http://python.org/
+.. _SimpleCookie: http://docs.python.org/library/cookie.html#morsel-objects
+.. _testing: http://github.com/defnull/bottle/raw/master/bottle.py
+
+========
+Tutorial
+========
+
+This tutorial introduces you to the concepts and features of the Bottle web framework and covers basic and advanced topics alike. You can read it from start to end, or use it as a reference later on. The automatically generated :doc:`api` may be interesting for you, too. It covers more details, but explains less than this tutorial. Solutions for the most common questions can be found in our :doc:`recipes` collection or on the :doc:`faq` page. If you need any help, join our `mailing list <mailto:bottlepy@googlegroups.com>`_ or visit us in our `IRC channel <http://webchat.freenode.net/?channels=bottlepy>`_.
+
+.. _installation:
+
+Installation
+==============================================================================
+
+Bottle does not depend on any external libraries. You can just download `bottle.py </bottle.py>`_ into your project directory and start coding:
+
+.. code-block:: bash
+
+    $ wget http://bottlepy.org/bottle.py
+
+This will get you the latest development snapshot that includes all the new features. If you prefer a more stable environment, you should stick with the stable releases. These are available on `PyPi <http://pypi.python.org/pypi/bottle>`_ and can be installed via :command:`pip` (recommended), :command:`easy_install` or your package manager:
+
+.. code-block:: bash
+
+    $ sudo pip install bottle              # recommended
+    $ sudo easy_install bottle             # alternative without pip
+    $ sudo apt-get install python-bottle   # works for debian, ubuntu, ...
+
+Either way, you'll need Python 2.5 or newer (including 3.x) to run bottle applications. If you do not have permissions to install packages system-wide or simply don't want to, create a `virtualenv <http://pypi.python.org/pypi/virtualenv>`_ first:
+
+.. code-block:: bash
+
+    $ virtualenv develop              # Create virtual environment
+    $ source develop/bin/activate     # Change default python to virtual one
+    (develop)$ pip install -U bottle  # Install bottle to virtual environment
+
+Or, if virtualenv is not installed on your system:
+
+.. code-block:: bash
+
+    $ wget https://raw.github.com/pypa/virtualenv/master/virtualenv.py
+    $ python virtualenv.py develop    # Create virtual environment
+    $ source develop/bin/activate     # Change default python to virtual one
+    (develop)$ pip install -U bottle  # Install bottle to virtual environment
+
+
+
+Quickstart: "Hello World"
+==============================================================================
+
+This tutorial assumes you have Bottle either :ref:`installed <installation>` or copied into your project directory. Let's start with a very basic "Hello World" example::
+
+    from bottle import route, run
+
+    @route('/hello')
+    def hello():
+        return "Hello World!"
+
+    run(host='localhost', port=8080, debug=True)
+
+This is it. Run this script, visit http://localhost:8080/hello and you will see "Hello World!" in your browser. Here is how it works:
+
+The :func:`route` decorator binds a piece of code to an URL path. In this case, we link the ``/hello`` URL to the ``hello()`` function. This is called a `route` (hence the decorator name) and is the most important concept of this framework. You can define as many routes as you want. Whenever a browser requests an URL, the associated function is called and the return value is sent back to the browser. Its as simple as that.
+
+The :func:`run` call in the last line starts a built-in development server. It runs on `localhost` port 8080 and serves requests until you hit :kbd:`Control-c`. You can switch the server backend later, but for now a development server is all we need. It requires no setup at all and is an incredibly painless way to get your application up and running for local tests.
+
+The :ref:`tutorial-debugging` is very helpful during early development, but should be switched off for public applications. Keep that in mind.
+
+Of course this is a very simple example, but it shows the basic concept of how applications are built with Bottle. Continue reading and you'll see what else is possible.
+
+.. _tutorial-default:
+
+The `Default Application`
+------------------------------------------------------------------------------
+
+For the sake of simplicity, most examples in this tutorial use a module-level :func:`route` decorator to define routes. This adds routes to a global "default application", an instance of :class:`Bottle` that is automatically created the first time you call :func:`route`. Several other module-level decorators and functions relate to this default application, but if you prefer a more object oriented approach and don't mind the extra typing, you can create a separate application object and use that instead of the global one::
+
+    from bottle import Bottle, run, template
+
+    app = Bottle()
+
+    @app.route('/hello')
+    def hello():
+        return "Hello World!"
+
+    run(app, host='localhost', port=8080)
+
+The object-oriented approach is further described in the :ref:`default-app` section. Just keep in mind that you have a choice.
+
+
+
+
+.. _tutorial-routing:
+
+Request Routing
+==============================================================================
+
+In the last chapter we built a very simple web application with only a single route. Here is the routing part of the "Hello World" example again::
+
+    @route('/hello')
+    def hello():
+        return "Hello World!"
+
+The :func:`route` decorator links an URL path to a callback function, and adds a new route to the :ref:`default application <tutorial-default>`. An application with just one route is kind of boring, though. Let's add some more::
+
+    @route('/')
+    @route('/hello/<name>')
+    def greet(name='Stranger'):
+        return template('Hello {{name}}, how are you?', name=name)
+
+This example demonstrates two things: You can bind more than one route to a single callback, and you can add wildcards to URLs and access them via keyword arguments.
+
+
+
+.. _tutorial-dynamic-routes:
+
+Dynamic Routes
+-------------------------------------------------------------------------------
+
+Routes that contain wildcards are called `dynamic routes` (as opposed to `static routes`) and match more than one URL at the same time. A simple wildcard consists of a name enclosed in angle brackets (e.g. ``<name>``) and accepts one or more characters up to the next slash (``/``). For example, the route ``/hello/<name>`` accepts requests for ``/hello/alice`` as well as ``/hello/bob``, but not for ``/hello``, ``/hello/`` or ``/hello/mr/smith``.
+
+Each wildcard passes the covered part of the URL as a keyword argument to the request callback. You can use them right away and implement RESTful, nice-looking and meaningful URLs with ease. Here are some other examples along with the URLs they'd match::
+
+    @route('/wiki/<pagename>')            # matches /wiki/Learning_Python
+    def show_wiki_page(pagename):
+        ...
+
+    @route('/<action>/<user>')            # matches /follow/defnull
+    def user_api(action, user):
+        ...
+
+.. versionadded:: 0.10
+
+Filters are used to define more specific wildcards, and/or transform the covered part of the URL before it is passed to the callback. A filtered wildcard is declared as ``<name:filter>`` or ``<name:filter:config>``. The syntax for the optional config part depends on the filter used.
+
+The following filters are implemented by default and more may be added:
+
+* **:int** matches (signed) digits only and converts the value to integer.
+* **:float** similar to :int but for decimal numbers.
+* **:path** matches all characters including the slash character in a non-greedy way and can be used to match more than one path segment.
+* **:re** allows you to specify a custom regular expression in the config field. The matched value is not modified.
+
+Let's have a look at some practical examples::
+
+    @route('/object/<id:int>')
+    def callback(id):
+        assert isinstance(id, int)
+
+    @route('/show/<name:re:[a-z]+>')
+    def callback(name):
+        assert name.isalpha()
+
+    @route('/static/<path:path>')
+    def callback(path):
+        return static_file(path, ...)
+
+You can add your own filters as well. See :doc:`Routing` for details.
+
+.. versionchanged:: 0.10
+
+The new rule syntax was introduced in **Bottle 0.10** to simplify some common use cases, but the old syntax still works and you can find a lot of code examples still using it. The differences are best described by example:
+
+=================== ====================
+Old Syntax          New Syntax
+=================== ====================
+``:name``           ``<name>``
+``:name#regexp#``   ``<name:re:regexp>``
+``:#regexp#``       ``<:re:regexp>``
+``:##``             ``<:re>``
+=================== ====================
+
+Try to avoid the old syntax in future projects if you can. It is not currently deprecated, but will be eventually.
+
+
+HTTP Request Methods
+------------------------------------------------------------------------------
+
+.. __: http_method_
+
+The HTTP protocol defines several `request methods`__ (sometimes referred to as "verbs") for different tasks. GET is the default for all routes with no other method specified. These routes will match GET requests only. To handle other methods such as POST, PUT or DELETE, add a ``method`` keyword argument to the :func:`route` decorator or use one of the four alternative decorators: :func:`get`, :func:`post`, :func:`put` or :func:`delete`.
+
+The POST method is commonly used for HTML form submission. This example shows how to handle a login form using POST::
+
+    from bottle import get, post, request
+
+    @get('/login') # or @route('/login')
+    def login_form():
+        return '''<form method="POST" action="/login">
+                    <input name="name"     type="text" />
+                    <input name="password" type="password" />
+                    <input type="submit" />
+                  </form>'''
+
+    @post('/login') # or @route('/login', method='POST')
+    def login_submit():
+        name     = request.forms.get('name')
+        password = request.forms.get('password')
+        if check_login(name, password):
+            return "<p>Your login was correct</p>"
+        else:
+            return "<p>Login failed</p>"
+
+In this example the ``/login`` URL is linked to two distinct callbacks, one for GET requests and another for POST requests. The first one displays a HTML form to the user. The second callback is invoked on a form submission and checks the login credentials the user entered into the form. The use of :attr:`Request.forms` is further described in the :ref:`tutorial-request` section.
+
+.. rubric:: Special Methods: HEAD and ANY
+
+The HEAD method is used to ask for the response identical to the one that would correspond to a GET request, but without the response body. This is useful for retrieving meta-information about a resource without having to download the entire document. Bottle handles these requests automatically by falling back to the corresponding GET route and cutting off the request body, if present. You don't have to specify any HEAD routes yourself.
+
+Additionally, the non-standard ANY method works as a low priority fallback: Routes that listen to ANY will match requests regardless of their HTTP method but only if no other more specific route is defined. This is helpful for *proxy-routes* that redirect requests to more specific sub-applications.
+
+To sum it up: HEAD requests fall back to GET routes and all requests fall back to ANY routes, but only if there is no matching route for the original request method. It's as simple as that.
+
+
+
+Routing Static Files
+------------------------------------------------------------------------------
+
+Static files such as images or CSS files are not served automatically. You have to add a route and a callback to control which files get served and where to find them::
+
+  from bottle import static_file
+  @route('/static/<filename>')
+  def server_static(filename):
+      return static_file(filename, root='/path/to/your/static/files')
+
+The :func:`static_file` function is a helper to serve files in a safe and convenient way (see :ref:`tutorial-static-files`). This example is limited to files directly within the ``/path/to/your/static/files`` directory because the ``<filename>`` wildcard won't match a path with a slash in it. To serve files in subdirectories, change the wildcard to use the `path` filter::
+
+  @route('/static/<filepath:path>')
+  def server_static(filepath):
+      return static_file(filepath, root='/path/to/your/static/files')
+
+Be careful when specifying a relative root-path such as ``root='./static/files'``. The working directory (``./``) and the project directory are not always the same.
+
+
+
+
+.. _tutorial-errorhandling:
+
+Error Pages
+------------------------------------------------------------------------------
+
+If anything goes wrong, Bottle displays an informative but fairly plain error page. You can override the default for a specific HTTP status code with the :func:`error` decorator::
+
+  from bottle import error
+  @error(404)
+  def error404(error):
+      return 'Nothing here, sorry'
+
+From now on, `404 File not Found` errors will display a custom error page to the user. The only parameter passed to the error-handler is an instance of :exc:`HTTPError`. Apart from that, an error-handler is quite similar to a regular request callback. You can read from :data:`request`, write to :data:`response` and return any supported data-type except for :exc:`HTTPError` instances.
+
+Error handlers are used only if your application returns or raises an :exc:`HTTPError` exception (:func:`abort` does just that). Changing :attr:`Request.status` or returning :exc:`HTTPResponse` won't trigger the error handler.
+
+
+
+
+
+
+.. _tutorial-output:
+
+Generating content
+==============================================================================
+
+In pure WSGI, the range of types you may return from your application is very limited. Applications must return an iterable yielding byte strings. You may return a string (because strings are iterable) but this causes most servers to transmit your content char by char. Unicode strings are not allowed at all. This is not very practical.
+
+Bottle is much more flexible and supports a wide range of types. It even adds a ``Content-Length`` header if possible and encodes unicode automatically, so you don't have to. What follows is a list of data types you may return from your application callbacks and a short description of how these are handled by the framework:
+
+Dictionaries
+    As mentioned above, Python dictionaries (or subclasses thereof) are automatically transformed into JSON strings and returned to the browser with the ``Content-Type`` header set to ``application/json``. This makes it easy to implement json-based APIs. Data formats other than json are supported too. See the :ref:`tutorial-output-filter` to learn more.
+
+Empty Strings, ``False``, ``None`` or other non-true values:
+    These produce an empty output with the ``Content-Length`` header set to 0.
+
+Unicode strings
+    Unicode strings (or iterables yielding unicode strings) are automatically encoded with the codec specified in the ``Content-Type`` header (utf8 by default) and then treated as normal byte strings (see below).
+
+Byte strings
+    Bottle returns strings as a whole (instead of iterating over each char) and adds a ``Content-Length`` header based on the string length. Lists of byte strings are joined first. Other iterables yielding byte strings are not joined because they may grow too big to fit into memory. The ``Content-Length`` header is not set in this case.
+
+Instances of :exc:`HTTPError` or :exc:`HTTPResponse`
+    Returning these has the same effect as when raising them as an exception. In case of an :exc:`HTTPError`, the error handler is applied. See :ref:`tutorial-errorhandling` for details.
+
+File objects
+    Everything that has a ``.read()`` method is treated as a file or file-like object and passed to the ``wsgi.file_wrapper`` callable defined by the WSGI server framework. Some WSGI server implementations can make use of optimized system calls (sendfile) to transmit files more efficiently. In other cases this just iterates over chunks that fit into memory. Optional headers such as ``Content-Length`` or ``Content-Type`` are *not* set automatically. Use :func:`send_file` if possible. See :ref:`tutorial-static-files` for details.
+
+Iterables and generators
+    You are allowed to use ``yield`` within your callbacks or return an iterable, as long as the iterable yields byte strings, unicode strings, :exc:`HTTPError` or :exc:`HTTPResponse` instances. Nested iterables are not supported, sorry. Please note that the HTTP status code and the headers are sent to the browser as soon as the iterable yields its first non-empty value. Changing these later has no effect.
+
+The ordering of this list is significant. You may for example return a subclass of :class:`str` with a ``read()`` method. It is still treated as a string instead of a file, because strings are handled first.
+
+.. rubric:: Changing the Default Encoding
+
+Bottle uses the `charset` parameter of the ``Content-Type`` header to decide how to encode unicode strings. This header defaults to ``text/html; charset=UTF8`` and can be changed using the :attr:`Response.content_type` attribute or by setting the :attr:`Response.charset` attribute directly. (The :class:`Response` object is described in the section :ref:`tutorial-response`.)
+
+::
+
+    from bottle import response
+    @route('/iso')
+    def get_iso():
+        response.charset = 'ISO-8859-15'
+        return u'This will be sent with ISO-8859-15 encoding.'
+
+    @route('/latin9')
+    def get_latin():
+        response.content_type = 'text/html; charset=latin9'
+        return u'ISO-8859-15 is also known as latin9.'
+
+In some rare cases the Python encoding names differ from the names supported by the HTTP specification. Then, you have to do both: first set the :attr:`Response.content_type` header (which is sent to the client unchanged) and then set the :attr:`Response.charset` attribute (which is used to encode unicode).
+
+.. _tutorial-static-files:
+
+Static Files
+--------------------------------------------------------------------------------
+
+You can directly return file objects, but :func:`static_file` is the recommended way to serve static files. It automatically guesses a mime-type, adds a ``Last-Modified`` header, restricts paths to a ``root`` directory for security reasons and generates appropriate error responses (401 on permission errors, 404 on missing files). It even supports the ``If-Modified-Since`` header and eventually generates a ``304 Not Modified`` response. You can pass a custom MIME type to disable guessing.
+
+::
+
+    from bottle import static_file
+    @route('/images/<filename:re:.*\.png>#')
+    def send_image(filename):
+        return static_file(filename, root='/path/to/image/files', mimetype='image/png')
+
+    @route('/static/<filename:path>')
+    def send_static(filename):
+        return static_file(filename, root='/path/to/static/files')
+
+You can raise the return value of :func:`static_file` as an exception if you really need to.
+
+.. rubric:: Forced Download
+
+Most browsers try to open downloaded files if the MIME type is known and assigned to an application (e.g. PDF files). If this is not what you want, you can force a download dialog and even suggest a filename to the user::
+
+    @route('/download/<filename:path>')
+    def download(filename):
+        return static_file(filename, root='/path/to/static/files', download=filename)
+
+If the ``download`` parameter is just ``True``, the original filename is used.
+
+.. _tutorial-error:
+
+HTTP Errors and Redirects
+--------------------------------------------------------------------------------
+
+The :func:`abort` function is a shortcut for generating HTTP error pages.
+
+::
+
+    from bottle import route, abort
+    @route('/restricted')
+    def restricted():
+        abort(401, "Sorry, access denied.")
+
+To redirect a client to a different URL, you can send a ``303 See Other`` response with the ``Location`` header set to the new URL. :func:`redirect` does that for you::
+
+    from bottle import redirect
+    @route('/wrong/url')
+    def wrong():
+        redirect("/right/url")
+
+You may provide a different HTTP status code as a second parameter.
+
+.. note::
+    Both functions will interrupt your callback code by raising an :exc:`HTTPError` exception.
+
+.. rubric:: Other Exceptions
+
+All exceptions other than :exc:`HTTPResponse` or :exc:`HTTPError` will result in a ``500 Internal Server Error`` response, so they won't crash your WSGI server. You can turn off this behavior to handle exceptions in your middleware by setting ``bottle.app().catchall`` to ``False``.
+
+
+.. _tutorial-response:
+
+The :class:`Response` Object
+--------------------------------------------------------------------------------
+
+Response metadata such as the HTTP status code, response headers and cookies are stored in an object called :data:`response` up to the point where they are transmitted to the browser. You can manipulate these metadata directly or use the predefined helper methods to do so. The full API and feature list is described in the API section (see :class:`Response`), but the most common use cases and features are covered here, too.
+
+.. rubric:: Status Code
+
+The `HTTP status code <http_code>`_ controls the behavior of the browser and defaults to ``200 OK``. In most scenarios you won't need to set the :attr:`Response.status` attribute manually, but use the :func:`abort` helper or return an :exc:`HTTPResponse` instance with the appropriate status code. Any integer is allowed, but codes other than the ones defined by the `HTTP specification <http_code>`_ will only confuse the browser and break standards.
+
+.. rubric:: Response Header
+
+Response headers such as ``Cache-Control`` or ``Location`` are defined via :meth:`Response.set_header`. This method takes two parameters, a header name and a value. The name part is case-insensitive::
+
+  @route('/wiki/<page>')
+  def wiki(page):
+      response.set_header('Content-Language', 'en')
+      ...
+
+Most headers are unique, meaning that only one header per name is send to the client. Some special headers however are allowed to appear more than once in a response. To add an additional header, use :meth:`Response.add_header` instead of :meth:`Response.set_header`::
+
+    response.set_header('Set-Cookie', 'name=value')
+    response.add_header('Set-Cookie', 'name2=value2')
+
+Please note that this is just an example. If you want to work with cookies, read :ref:`ahead <tutorial-cookies>`.
+
+
+.. _tutorial-cookies:
+
+Cookies
+-------------------------------------------------------------------------------
+
+A cookie is a named piece of text stored in the user's browser profile. You can access previously defined cookies via :meth:`Request.get_cookie` and set new cookies with :meth:`Response.set_cookie`::
+
+    @route('/hello')
+    def hello_again():
+        if request.get_cookie("visited"):
+            return "Welcome back! Nice to see you again"
+        else:
+            response.set_cookie("visited", "yes")
+            return "Hello there! Nice to meet you"
+
+The :meth:`Response.set_cookie` method accepts a number of additional keyword arguments that control the cookies lifetime and behavior. Some of the most common settings are described here:
+
+* **max_age:**    Maximum age in seconds. (default: ``None``)
+* **expires:**    A datetime object or UNIX timestamp. (default: ``None``)
+* **domain:**     The domain that is allowed to read the cookie. (default: current domain)
+* **path:**       Limit the cookie to a given path (default: ``/``)
+* **secure:**     Limit the cookie to HTTPS connections (default: off).
+* **httponly:**   Prevent client-side javascript to read this cookie (default: off, requires Python 2.6 or newer).
+
+If neither `expires` nor `max_age` is set, the cookie expires at the end of the browser session or as soon as the browser window is closed. There are some other gotchas you should consider when using cookies:
+
+* Cookies are limited to 4 KB of text in most browsers.
+* Some users configure their browsers to not accept cookies at all. Most search engines ignore cookies too. Make sure that your application still works without cookies.
+* Cookies are stored at client side and are not encrypted in any way. Whatever you store in a cookie, the user can read it. Worse than that, an attacker might be able to steal a user's cookies through `XSS <http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_theft_and_session_hijacking>`_ vulnerabilities on your side. Some viruses are known to read the browser cookies, too. Thus, never store confidential information in cookies.
+* Cookies are easily forged by malicious clients. Do not trust cookies.
+
+.. _tutorial-signed-cookies:
+
+.. rubric:: Signed Cookies
+
+As mentioned above, cookies are easily forged by malicious clients. Bottle can cryptographically sign your cookies to prevent this kind of manipulation. All you have to do is to provide a signature key via the `secret` keyword argument whenever you read or set a cookie and keep that key a secret. As a result, :meth:`Request.get_cookie` will return ``None`` if the cookie is not signed or the signature keys don't match::
+
+    @route('/login')
+    def login():
+        username = request.forms.get('username')
+        password = request.forms.get('password')
+        if check_user_credentials(username, password):
+            response.set_cookie("account", username, secret='some-secret-key')
+            return "Welcome %s! You are now logged in." % username
+        else:
+            return "Login failed."
+
+    @route('/restricted')
+    def restricted_area():
+        username = request.get_cookie("account", secret='some-secret-key')
+        if username:
+            return "Hello %s. Welcome back." % username
+        else:
+            return "You are not logged in. Access denied."
+
+In addition, Bottle automatically pickles and unpickles any data stored to signed cookies. This allows you to store any pickle-able object (not only strings) to cookies, as long as the pickled data does not exceed the 4 KB limit.
+
+.. warning:: Signed cookies are not encrypted (the client can still see the content) and not copy-protected (the client can restore an old cookie). The main intention is to make pickling and unpickling safe and prevent manipulation, not to store secret information at client side.
+
+
+
+
+
+
+
+
+
+.. _tutorial-request:
+
+Request Data
+==============================================================================
+
+Bottle provides access to HTTP-related metadata such as cookies, headers and POST form data through a global ``request`` object. This object always contains information about the *current* request, as long as it is accessed from within a callback function. This works even in multi-threaded environments where multiple requests are handled at the same time. For details on how a global object can be thread-safe, see :doc:`contextlocal`.
+
+.. note::
+
+    Bottle stores most of the parsed HTTP metadata in :class:`FormsDict` instances. These behave like normal dictionaries, but have some additional features: All values in the dictionary are available as attributes. These virtual attributes always return a unicode string, even if the value is missing. In that case, the string is empty.
+
+    :class:`FormsDict` is a subclass of :class:`MultiDict` and can store more than one value per key. The standard dictionary access methods will only return a single value, but the :meth:`MultiDict.getall` method returns a (possibly empty) list of all values for a specific key.
+
+The full API and feature list is described in the API section (see :class:`Request`), but the most common use cases and features are covered here, too.
+
+
+Cookies
+--------------------------------------------------------------------------------
+
+Cookies are stored in :attr:`BaseRequest.cookies` as a :class:`FormsDict`. The :meth:`BaseRequest.get_cookie` method allows access to :ref:`signed cookies <tutorial-signed-cookies>` as described in a separate section. This example shows a simple cookie-based view counter::
+
+  from bottle import route, request, response
+  @route('/counter')
+  def counter():
+      count = int( request.cookies.get('counter', '0') )
+      count += 1
+      response.set_cookie('counter', str(count))
+      return 'You visited this page %d times' % count
+
+
+HTTP Headers
+--------------------------------------------------------------------------------
+
+All HTTP headers sent by the client (e.g. ``Referer``, ``Agent`` or ``Accept-Language``) are stored in a :class:`WSGIHeaderDict` and accessible through :attr:`BaseRequest.headers`. A :class:`WSGIHeaderDict` is basically a dictionary with case-insensitive keys::
+
+  from bottle import route, request
+  @route('/is_ajax')
+  def is_ajax():
+      if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
+          return 'This is an AJAX request'
+      else:
+          return 'This is a normal request'
+
+
+Query Variables
+--------------------------------------------------------------------------------
+
+The query string (as in ``/forum?id=1&page=5``) is commonly used to transmit a small number of key/value pairs to the server. You can use the :attr:`BaseRequest.query` (a :class:`FormsDict`) to access these values and the :attr:`BaseRequest.query_string` attribute to get the whole string.
+
+::
+
+  from bottle import route, request, response
+  @route('/forum')
+  def display_forum():
+      forum_id = request.query.id
+      page = request.query.page or '1'
+      return 'Forum ID: %s (page %s)' % (forum_id, page)
+
+
+POST Form Data and File Uploads
+-------------------------------
+
+The request body of ``POST`` and ``PUT`` requests may contain form data encoded in various formats. The :attr:`BaseRequest.forms` dictionary contains parsed textual form fields, :attr:`BaseRequest.files` stores file uploads and :attr:`BaseRequest.POST` combines both dictionaries into one. All three are :class:`FormsDict` instances and are created on demand. File uploads are saved as special :class:`cgi.FieldStorage` objects along with some metadata. Finally, you can access the raw body data as a file-like object via :attr:`BaseRequest.body`.
+
+Here is an example for a simple file upload form:
+
+.. code-block:: html
+
+    <form action="/upload" method="post" enctype="multipart/form-data">
+      <input type="text" name="name" />
+      <input type="file" name="data" />
+    </form>
+
+::
+
+    from bottle import route, request
+    @route('/upload', method='POST')
+    def do_upload():
+        name = request.forms.name
+        data = request.files.data
+        if name and data and data.file:
+            raw = data.file.read() # This is dangerous for big files
+            filename = data.filename
+            return "Hello %s! You uploaded %s (%d bytes)." % (name, filename, len(raw))
+        return "You missed a field."
+
+
+Unicode issues
+-----------------------
+
+In **Python 2** all keys and values are byte-strings. If you need unicode, you can call :meth:`FormsDict.getunicode` or fetch values via attribute access. Both methods try to decode the string (default: utf8) and return an empty string if that fails. No need to catch :exc:`UnicodeError`::
+
+  >>> request.query['city']
+  'G\xc3\xb6ttingen'  # A utf8 byte string
+  >>> request.query.city
+  u'Göttingen'        # The same string as unicode
+
+In **Python 3** all strings are unicode, but HTTP is a byte-based wire protocol. The server has to decode the byte strings somehow before they are passed to the application. To be on the safe side, WSGI suggests ISO-8859-1 (aka latin1), a reversible single-byte codec that can be re-encoded with a different encoding later. Bottle does that for :meth:`FormsDict.getunicode` and attribute access, but not for the dict-access methods. These return the unchanged values as provided by the server implementation, which is probably not what you want.
+
+  >>> request.query['city']
+  'Göttingen' # An utf8 string provisionally decoded as ISO-8859-1 by the server
+  >>> request.query.city
+  'Göttingen'  # The same string correctly re-encoded as utf8 by bottle
+
+If you need the whole dictionary with correctly decoded values (e.g. for WTForms), you can call :meth:`FormsDict.decode` to get a re-encoded copy.
+
+
+WSGI Environment
+--------------------------------------------------------------------------------
+
+Each :class:`BaseRequest` instance wraps a WSGI environment dictionary. The original is stored in :attr:`BaseRequest.environ`, but the request object itself behaves like a dictionary, too. Most of the interesting data is exposed through special methods or attributes, but if you want to access `WSGI environ variables <WSGI specification>`_ directly, you can do so::
+
+  @route('/my_ip')
+  def show_ip():
+      ip = request.environ.get('REMOTE_ADDR')
+      # or ip = request.get('REMOTE_ADDR')
+      # or ip = request['REMOTE_ADDR']
+      return "Your IP is: %s" % ip
+
+
+
+
+
+
+
+.. _tutorial-templates:
+
+Templates
+================================================================================
+
+Bottle comes with a fast and powerful built-in template engine called :doc:`stpl`. To render a template you can use the :func:`template` function or the :func:`view` decorator. All you have to do is to provide the name of the template and the variables you want to pass to the template as keyword arguments. Here’s a simple example of how to render a template::
+
+    @route('/hello')
+    @route('/hello/<name>')
+    def hello(name='World'):
+        return template('hello_template', name=name)
+
+This will load the template file ``hello_template.tpl`` and render it with the ``name`` variable set. Bottle will look for templates in the ``./views/`` folder or any folder specified in the ``bottle.TEMPLATE_PATH`` list.
+
+The :func:`view` decorator allows you to return a dictionary with the template variables instead of calling :func:`template`::
+
+    @route('/hello')
+    @route('/hello/<name>')
+    @view('hello_template')
+    def hello(name='World'):
+        return dict(name=name)
+
+.. rubric:: Syntax
+
+.. highlight:: html+django
+
+The template syntax is a very thin layer around the Python language. Its main purpose is to ensure correct indentation of blocks, so you can format your template without worrying about indentation. Follow the link for a full syntax description: :doc:`stpl`
+
+Here is an example template::
+
+    %if name == 'World':
+        <h1>Hello {{name}}!</h1>
+        <p>This is a test.</p>
+    %else:
+        <h1>Hello {{name.title()}}!</h1>
+        <p>How are you?</p>
+    %end
+
+.. rubric:: Caching
+
+Templates are cached in memory after compilation. Modifications made to the template files will have no affect until you clear the template cache. Call ``bottle.TEMPLATES.clear()`` to do so. Caching is disabled in debug mode.
+
+.. highlight:: python
+
+
+
+
+.. _plugins:
+
+Plugins
+================================================================================
+
+.. versionadded:: 0.9
+
+Bottle's core features cover most common use-cases, but as a micro-framework it has its limits. This is where "Plugins" come into play. Plugins add missing functionality to the framework, integrate third party libraries, or just automate some repetitive work.
+
+We have a growing :doc:`/plugins/index` and most plugins are designed to be portable and re-usable across applications. The chances are high that your problem has already been solved and a ready-to-use plugin exists. If not, the :doc:`/plugindev` may help you.
+
+The effects and APIs of plugins are manifold and depend on the specific plugin. The ``SQLitePlugin`` plugin for example detects callbacks that require a ``db`` keyword argument and creates a fresh database connection object every time the callback is called. This makes it very convenient to use a database::
+
+    from bottle import route, install, template
+    from bottle_sqlite import SQLitePlugin
+
+    install(SQLitePlugin(dbfile='/tmp/test.db'))
+
+    @route('/show/<post_id:int>')
+    def show(db, post_id):
+        c = db.execute('SELECT title, content FROM posts WHERE id = ?', (post_id,))
+        row = c.fetchone()
+        return template('show_post', title=row['title'], text=row['content'])
+
+    @route('/contact')
+    def contact_page():
+        ''' This callback does not need a db connection. Because the 'db'
+            keyword argument is missing, the sqlite plugin ignores this callback
+            completely. '''
+        return template('contact')
+
+Other plugin may populate the thread-safe :data:`local` object, change details of the :data:`request` object, filter the data returned by the callback or bypass the callback completely. An "auth" plugin for example could check for a valid session and return a login page instead of calling the original callback. What happens exactly depends on the plugin.
+
+
+Application-wide Installation
+--------------------------------------------------------------------------------
+
+Plugins can be installed application-wide or just to some specific routes that need additional functionality. Most plugins can safely be installed to all routes and are smart enough to not add overhead to callbacks that do not need their functionality.
+
+Let us take the ``SQLitePlugin`` plugin for example. It only affects route callbacks that need a database connection. Other routes are left alone. Because of this, we can install the plugin application-wide with no additional overhead.
+
+To install a plugin, just call :func:`install` with the plugin as first argument::
+
+    from bottle_sqlite import SQLitePlugin
+    install(SQLitePlugin(dbfile='/tmp/test.db'))
+
+The plugin is not applied to the route callbacks yet. This is delayed to make sure no routes are missed. You can install plugins first and add routes later, if you want to. The order of installed plugins is significant, though. If a plugin requires a database connection, you need to install the database plugin first.
+
+
+.. rubric:: Uninstall Plugins
+
+You can use a name, class or instance to :func:`uninstall` a previously installed plugin::
+
+    sqlite_plugin = SQLitePlugin(dbfile='/tmp/test.db')
+    install(sqlite_plugin)
+
+    uninstall(sqlite_plugin) # uninstall a specific plugin
+    uninstall(SQLitePlugin)  # uninstall all plugins of that type
+    uninstall('sqlite')      # uninstall all plugins with that name
+    uninstall(True)          # uninstall all plugins at once
+
+Plugins can be installed and removed at any time, even at runtime while serving requests. This enables some neat tricks (installing slow debugging or profiling plugins only when needed) but should not be overused. Each time the list of plugins changes, the route cache is flushed and all plugins are re-applied.
+
+.. note::
+    The module-level :func:`install` and :func:`uninstall` functions affect the :ref:`default-app`. To manage plugins for a specific application, use the corresponding methods on the :class:`Bottle` application object.
+
+
+Route-specific Installation
+--------------------------------------------------------------------------------
+
+The ``apply`` parameter of the :func:`route` decorator comes in handy if you want to install plugins to only a small number of routes::
+
+    sqlite_plugin = SQLitePlugin(dbfile='/tmp/test.db')
+
+    @route('/create', apply=[sqlite_plugin])
+    def create(db):
+        db.execute('INSERT INTO ...')
+
+
+Blacklisting Plugins
+--------------------------------------------------------------------------------
+
+You may want to explicitly disable a plugin for a number of routes. The :func:`route` decorator has a ``skip`` parameter for this purpose::
+
+    sqlite_plugin = SQLitePlugin(dbfile='/tmp/test.db')
+    install(sqlite_plugin)
+
+    @route('/open/<db>', skip=[sqlite_plugin])
+    def open_db(db):
+        # The 'db' keyword argument is not touched by the plugin this time.
+        if db in ('test', 'test2'):
+            # The plugin handle can be used for runtime configuration, too.
+            sqlite_plugin.dbfile = '/tmp/%s.db' % db
+            return "Database File switched to: /tmp/%s.db" % db
+        abort(404, "No such database.")
+
+The ``skip`` parameter accepts a single value or a list of values. You can use a name, class or instance to identify the plugin that is to be skipped. Set ``skip=True`` to skip all plugins at once.
+
+Plugins and Sub-Applications
+--------------------------------------------------------------------------------
+
+Most plugins are specific to the application they were installed to. Consequently, they should not affect sub-applications mounted with :meth:`Bottle.mount`. Here is an example::
+
+    root = Bottle()
+    root.mount('/blog', apps.blog)
+
+    @root.route('/contact', template='contact')
+    def contact():
+        return {'email': 'contact@example.com'}
+
+    root.install(plugins.WTForms())
+
+Whenever you mount an application, Bottle creates a proxy-route on the main-application that forwards all requests to the sub-application. Plugins are disabled for this kind of proxy-route by default. As a result, our (fictional) `WTForms` plugin affects the ``/contact`` route, but does not affect the routes of the ``/blog`` sub-application.
+
+This behavior is intended as a sane default, but can be overridden. The following example re-activates all plugins for a specific proxy-route::
+
+    root.mount('/blog', apps.blog, skip=None)
+
+But there is a snag: The plugin sees the whole sub-application as a single route, namely the proxy-route mentioned above. In order to affect each individual route of the sub-application, you have to install the plugin to the mounted application explicitly.
+
+
+
+Development
+================================================================================
+
+So you have learned the basics and want to write your own application? Here are
+some tips that might help you to be more productive.
+
+.. _default-app:
+
+Default Application
+--------------------------------------------------------------------------------
+
+Bottle maintains a global stack of :class:`Bottle` instances and uses the top of the stack as a default for some of the module-level functions and decorators. The :func:`route` decorator, for example, is a shortcut for calling :meth:`Bottle.route` on the default application::
+
+    @route('/')
+    def hello():
+        return 'Hello World'
+
+This is very convenient for small applications and saves you some typing, but also means that, as soon as your module is imported, routes are installed to the global application. To avoid this kind of import side-effects, Bottle offers a second, more explicit way to build applications::
+
+    app = Bottle()
+
+    @app.route('/')
+    def hello():
+        return 'Hello World'
+
+Separating the application object improves re-usability a lot, too. Other developers can safely import the ``app`` object from your module and use :meth:`Bottle.mount` to merge applications together.
+
+As an alternative, you can make use of the application stack to isolate your routes while still using the convenient shortcuts::
+
+    default_app.push()
+
+    @route('/')
+    def hello():
+        return 'Hello World'
+
+    app = default_app.pop()
+
+Both :func:`app` and :func:`default_app` are instance of :class:`AppStack` and implement a stack-like API. You can push and pop applications from and to the stack as needed. This also helps if you want to import a third party module that does not offer a separate application object::
+
+    default_app.push()
+
+    import some.module
+
+    app = default_app.pop()
+
+
+.. _tutorial-debugging:
+
+
+Debug Mode
+--------------------------------------------------------------------------------
+
+During early development, the debug mode can be very helpful.
+
+.. highlight:: python
+
+::
+
+    bottle.debug(True)
+
+In this mode, Bottle is much more verbose and provides helpful debugging information whenever an error occurs. It also disables some optimisations that might get in your way and adds some checks that warn you about possible misconfiguration.
+
+Here is an incomplete list of things that change in debug mode:
+
+* The default error page shows a traceback.
+* Templates are not cached.
+* Plugins are applied immediately.
+
+Just make sure not to use the debug mode on a production server.
+
+Auto Reloading
+--------------------------------------------------------------------------------
+
+During development, you have to restart the server a lot to test your
+recent changes. The auto reloader can do this for you. Every time you
+edit a module file, the reloader restarts the server process and loads
+the newest version of your code.
+
+::
+
+    from bottle import run
+    run(reloader=True)
+
+How it works: the main process will not start a server, but spawn a new
+child process using the same command line arguments used to start the
+main process. All module-level code is executed at least twice! Be
+careful.
+
+The child process will have ``os.environ['BOTTLE_CHILD']`` set to ``True``
+and start as a normal non-reloading app server. As soon as any of the
+loaded modules changes, the child process is terminated and re-spawned by
+the main process. Changes in template files will not trigger a reload.
+Please use debug mode to deactivate template caching.
+
+The reloading depends on the ability to stop the child process. If you are
+running on Windows or any other operating system not supporting
+``signal.SIGINT`` (which raises ``KeyboardInterrupt`` in Python),
+``signal.SIGTERM`` is used to kill the child. Note that exit handlers and
+finally clauses, etc., are not executed after a ``SIGTERM``.
+
+
+Command Line Interface
+--------------------------------------------------------------------------------
+
+.. versionadded: 0.10
+
+Starting with version 0.10 you can use bottle as a command-line tool:
+
+.. code-block:: console
+
+    $ python -m bottle
+
+    Usage: bottle.py [options] package.module:app
+
+    Options:
+      -h, --help            show this help message and exit
+      --version             show version number.
+      -b ADDRESS, --bind=ADDRESS
+                            bind socket to ADDRESS.
+      -s SERVER, --server=SERVER
+                            use SERVER as backend.
+      -p PLUGIN, --plugin=PLUGIN
+                            install additional plugin/s.
+      --debug               start server in debug mode.
+      --reload              auto-reload on file changes.
+
+The `ADDRESS` field takes an IP address or an IP:PORT pair and defaults to ``localhost:8080``. The other parameters should be self-explanatory.
+
+Both plugins and applications are specified via import expressions. These consist of an import path (e.g. ``package.module``) and an expression to be evaluated in the namespace of that module, separated by a colon. See :func:`load` for details. Here are some examples:
+
+.. code-block:: console
+
+    # Grab the 'app' object from the 'myapp.controller' module and
+    # start a paste server on port 80 on all interfaces.
+    python -m bottle -server paste -bind 0.0.0.0:80 myapp.controller:app
+
+    # Start a self-reloading development server and serve the global
+    # default application. The routes are defined in 'test.py'
+    python -m bottle --debug --reload test
+
+    # Install a custom debug plugin with some parameters
+    python -m bottle --debug --reload --plugin 'utils:DebugPlugin(exc=True)'' test
+
+    # Serve an application that is created with 'myapp.controller.make_app()'
+    # on demand.
+    python -m bottle 'myapp.controller:make_app()''
+
+
+Deployment
+================================================================================
+
+Bottle runs on the built-in `wsgiref WSGIServer <http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server>`_  by default. This non-threading HTTP server is perfectly fine for development and early production, but may become a performance bottleneck when server load increases.
+
+The easiest way to increase performance is to install a multi-threaded server library like paste_ or cherrypy_ and tell Bottle to use that instead of the single-threaded server::
+
+    bottle.run(server='paste')
+
+This, and many other deployment options are described in a separate article: :doc:`deployment`
+
+
+
+
+.. _tutorial-glossary:
+
+Glossary
+========
+
+.. glossary::
+
+   callback
+      Programmer code that is to be called when some external action happens.
+      In the context of web frameworks, the mapping between URL paths and
+      application code is often achieved by specifying a callback function
+      for each URL.
+
+   decorator
+      A function returning another function, usually applied as a function transformation using the ``@decorator`` syntax. See `python documentation for function definition  <http://docs.python.org/reference/compound_stmts.html#function>`_ for more about decorators.
+
+   environ
+      A structure where information about all documents under the root is
+      saved, and used for cross-referencing.  The environment is pickled
+      after the parsing stage, so that successive runs only need to read
+      and parse new and changed documents.
+
+   handler function
+      A function to handle some specific event or situation. In a web
+      framework, the application is developed by attaching a handler function
+      as callback for each specific URL comprising the application.
+
+   source directory
+      The directory which, including its subdirectories, contains all
+      source files for one Sphinx project.
+
diff --git a/html/_sources/tutorial_app.txt b/html/_sources/tutorial_app.txt
new file mode 100644 (file)
index 0000000..0b41ee0
--- /dev/null
@@ -0,0 +1,711 @@
+.. _Bottle: http://bottle.paws.org
+.. _Python: http://www.python.org
+.. _SQLite: http://www.sqlite.org
+.. _Windows: http://www.sqlite.org/download.html
+.. _PySQLite: http://pypi.python.org/pypi/pysqlite/
+.. _`decorator statement`: http://docs.python.org/glossary.html#term-decorator
+.. _`Python DB API`: http://www.python.org/dev/peps/pep-0249/
+.. _`WSGI reference Server`: http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server
+.. _Cherrypy: http://www.cherrypy.org/
+.. _Fapws3: http://github.com/william-os4y/fapws3
+.. _Flup: http://trac.saddi.com/flup
+.. _Paste: http://pythonpaste.org/
+.. _Apache: http://www.apache.org
+.. _`Bottle documentation`: http://bottlepy.org/docs/dev/tutorial.html
+.. _`mod_wsgi`: http://code.google.com/p/modwsgi/
+.. _`json`: http://www.json.org
+
+===============================
+Tutorial: Todo-List Application
+===============================
+
+.. note::
+
+   This tutorial is a work in progess and written by `noisefloor <http://github.com/noisefloor>`_.
+
+
+This tutorial should give a brief introduction to the Bottle_ WSGI Framework. The main goal is to be able, after reading through this tutorial, to create a project using Bottle. Within this document, not all abilities will be shown, but at least the main and important ones like routing, utilizing the Bottle template abilities to format output and handling GET / POST parameters.
+
+To understand the content here, it is not necessary to have a basic knowledge of WSGI, as Bottle tries to keep WSGI away from the user anyway. You should have a fair understanding of the Python_ programming language. Furthermore, the example used in the tutorial retrieves and stores data in a SQL databse, so a basic idea about SQL helps, but is not a must to understand the concepts of Bottle. Right here, SQLite_ is used. The output of Bottle sent to the browser is formatted in some examples by the help of HTML. Thus, a basic idea about the common HTML tags does help as well.
+
+For the sake of introducing Bottle, the Python code "in between" is kept short, in order to keep the focus. Also all code within the tutorial is working fine, but you may not necessarily use it "in the wild", e.g. on a public web server. In order to do so, you may add e.g. more error handling, protect the database with a password, test and escape the input etc.
+
+.. contents:: Table of Contents
+
+Goals
+===========
+
+At the end of this tutorial, we will have a simple, web-based ToDo list. The list contains a text (with max 100 characters) and a status (0 for closed, 1 for open) for each item. Through the web-based user interface, open items can be view and edited and new items can be added.
+
+During development, all pages will be available on ``localhost`` only, but later on it will be shown how to adapt the application for a "real" server, including how to use with Apache's mod_wsgi.
+
+Bottle will do the routing and format the output, with the help of templates. The items of the list will be stored inside a SQLite database. Reading and  writing the database will be done by Python code.
+
+We will end up with an application with the following pages and functionality:
+
+ * start page ``http://localhost:8080/todo``
+ * adding new items to the list: ``http://localhost:8080/new``
+ * page for editing items: ``http://localhost:8080/edit/:no``
+ * validating data assigned by dynamic routes with the @validate decorator
+ * catching errors
+
+Before We Start...
+====================
+
+
+.. rubric:: Install Bottle
+
+Assuming that you have a fairly new installation of Python (version 2.5 or higher), you only need to install Bottle in addition to that. Bottle has no other dependencies than Python itself.
+
+You can either manually install Bottle or use Python's easy_install: ``easy_install bottle``
+
+
+.. rubric:: Further Software Necessities
+
+As we use SQLite3 as a database, make sure it is installed. On Linux systems, most distributions have SQLite3 installed by default. SQLite is available for Windows and MacOS X as well and the `sqlite3` module is part of the python standard library.
+
+.. rubric:: Create An SQL Database
+
+First, we need to create the database we use later on. To do so, save the following script in your project directory and run it with python. You can use the interactive interpreter too::
+
+    import sqlite3
+    con = sqlite3.connect('todo.db') # Warning: This file is created in the current directory
+    con.execute("CREATE TABLE todo (id INTEGER PRIMARY KEY, task char(100) NOT NULL, status bool NOT NULL)")
+    con.execute("INSERT INTO todo (task,status) VALUES ('Read A-byte-of-python to get a good introduction into Python',0)")
+    con.execute("INSERT INTO todo (task,status) VALUES ('Visit the Python website',1)")
+    con.execute("INSERT INTO todo (task,status) VALUES ('Test various editors for and check the syntax highlighting',1)")
+    con.execute("INSERT INTO todo (task,status) VALUES ('Choose your favorite WSGI-Framework',0)")
+    con.commit()
+
+This generates a database-file `todo.db` with tables called ``todo`` and three columns ``id``, ``task``, and ``status``. ``id`` is a unique id for each row, which is used later on to reference the rows. The column ``task`` holds the text which describes the task, it can be max 100 characters long. Finally, the column ``status`` is used to mark a task as open (value 1) or closed (value 0).
+
+Using Bottle for a Web-Based ToDo List
+================================================
+
+Now it is time to introduce Bottle in order to create a web-based application. But first, we need to look into a basic concept of Bottle: routes.
+
+
+.. rubric:: Understanding routes
+
+Basically, each page visible in the browser is dynamically generated when the page address is called. Thus, there is no static content. That is exactly what is called a "route" within Bottle: a certain address on the server. So, for example, when the page ``http://localhost:8080/todo`` is called from the browser, Bottle "grabs" the call and checks if there is any (Python) function defined for the route "todo". If so, Bottle will execute the corresponding Python code and return its result.
+
+
+.. rubric:: First Step - Showing All Open Items
+
+So, after understanding the concept of routes, let's create the first one. The goal is to see all open items from the ToDo list::
+
+    import sqlite3
+    from bottle import route, run
+
+    @route('/todo')
+    def todo_list():
+        conn = sqlite3.connect('todo.db')
+        c = conn.cursor()
+        c.execute("SELECT id, task FROM todo WHERE status LIKE '1'")
+        result = c.fetchall()
+        return str(result)
+
+    run()
+
+Save the code a ``todo.py``, preferably in the same directory as the file ``todo.db``. Otherwise, you need to add the path to ``todo.db`` in the ``sqlite3.connect()`` statement.
+
+Let's have a look what we just did: We imported the necessary module ``sqlite3`` to access to SQLite database and from Bottle we imported ``route`` and ``run``. The ``run()`` statement simply starts the web server included in Bottle. By default, the web server serves the pages on localhost and port 8080. Furthermore, we imported ``route``, which is the function responsible for Bottle's routing. As you can see, we defined one function, ``todo_list()``, with a few lines of code reading from the database. The important point is the `decorator statement`_ ``@route('/todo')`` right before the ``def todo_list()`` statement. By doing this, we bind this function to the route ``/todo``, so every time the browsers calls ``http://localhost:8080/todo``, Bottle returns the result of the function ``todo_list()``. That is how routing within bottle works.
+
+Actually you can bind more than one route to a function. So the following code::
+
+    @route('/todo')
+    @route('/my_todo_list')
+    def todo_list():
+        ...
+
+will work fine, too. What will not work is to bind one route to more than one function.
+
+What you will see in the browser is what is returned, thus the value given by the ``return`` statement. In this example, we need to convert ``result`` in to a string by ``str()``, as Bottle expects a string or a list of strings from the return statement. But here, the result of the database query is a list of tuples, which is the standard defined by the `Python DB API`_.
+
+Now, after understanding the little script above, it is time to execute it and watch the result yourself. Remember that on Linux- / Unix-based systems the file ``todo.py`` needs to be executable first. Then, just run ``python todo.py`` and call the page ``http://localhost:8080/todo`` in your browser. In case you made no mistake writing the script, the output should look like this::
+
+    [(2, u'Visit the Python website'), (3, u'Test various editors for and check the syntax highlighting')]
+
+If so - congratulations! You are now a successful user of Bottle. In case it did not work and you need to make some changes to the script, remember to stop Bottle serving the page, otherwise the revised version will not be loaded.
+
+Actually, the output is not really exciting nor nice to read. It is the raw result returned from the SQL query.
+
+So, in the next step we format the output in a nicer way. But before we do that, we make our life easier.
+
+
+.. rubric:: Debugging and Auto-Reload
+
+Maybe you already noticed that Bottle sends a short error message to the browser in case something within the script is wrong, e.g. the connection to the database is not working. For debugging purposes it is quite helpful to get more details. This can be easily achieved by adding the following statement to the script::
+
+    from bottle import run, route, debug
+    ...
+    #add this at the very end:
+    debug(True)
+    run()
+
+By enabling "debug", you will get a full stacktrace of the Python interpreter, which usually contains useful information for finding bugs. Furthermore, templates (see below) are not cached, thus changes to templates will take effect without stopping the server.
+
+.. warning::
+
+   That ``debug(True)`` is supposed to be used for development only, it should *not* be used in production environments.
+
+
+
+A further quiet nice feature is auto-reloading, which is enabled by modifying the ``run()`` statement to
+
+::
+
+    run(reloader=True)
+
+This will automatically detect changes to the script and reload the new version once it is called again, without the need to stop and start the server.
+
+Again, the feature is mainly supposed to be used while development, not on productive systems.
+
+
+.. rubric:: Bottle Template To Format The Output
+
+Now let's have a look at casting the output of the script into a proper format.
+
+Actually Bottle expects to receive a string or a list of strings from a function and returns them by the help of the built-in server to the browser. Bottle does not bother about the content of the string itself, so it can be text formatted with HTML markup, too.
+
+Bottle brings its own easy-to-use template engine with it. Templates are stored as separate files having a ``.tpl`` extension. The template can be called then from within a function. Templates can contain any type of text (which will be most likely HTML-markup mixed with Python statements). Furthermore, templates can take arguments, e.g. the result set of a database query, which will be then formatted nicely within the template.
+
+Right here, we are going to cast the result of our query showing the open ToDo items into a simple table with two columns: the first column will contain the ID of the item, the second column the text. The result set is, as seen above, a list of tuples, each tuple contains one set of results.
+
+To include the template in our example, just add the following lines::
+
+    from bottle import route, run, debug, template
+    ...
+    result = c.fetchall()
+    c.close()
+    output = template('make_table', rows=result)
+    return output
+    ...
+
+So we do here two things: first, we import ``template`` from Bottle in order to be able to use templates. Second, we assign the output of the template ``make_table`` to the variable ``output``, which is then returned. In addition to calling the template, we assign ``result``, which we received from the database query, to the variable ``rows``, which is later on used within the template. If necessary, you can assign more than one variable / value to a template.
+
+Templates always return a list of strings, thus there is no need to convert anything. Of course, we can save one line of code by writing ``return template('make_table', rows=result)``, which gives exactly the same result as above.
+
+Now it is time to write the corresponding template, which looks like this::
+
+    %#template to generate a HTML table from a list of tuples (or list of lists, or tuple of tuples or ...)
+    <p>The open items are as follows:</p>
+    <table border="1">
+    %for row in rows:
+      <tr>
+      %for col in row:
+        <td>{{col}}</td>
+      %end
+      </tr>
+    %end
+    </table>
+
+Save the code as ``make_table.tpl`` in the same directory where ``todo.py`` is stored.
+
+Let's have a look at the code: every line starting with % is interpreted as Python code. Please note that, of course, only valid Python statements are allowed, otherwise the template will raise an exception, just as any other Python code. The other lines are plain HTML markup.
+
+As you can see, we use Python's ``for`` statement two times, in order to go through ``rows``. As seen above, ``rows`` is a variable which holds the result of the database query, so it is a list of tuples. The first ``for`` statement accesses the tuples within the list, the second one the items within the tuple, which are put each into a cell of the table. It is important that you close all ``for``, ``if``, ``while`` etc. statements with ``%end``, otherwise the output may not be what you expect.
+
+If you need to access a variable within a non-Python code line inside the template, you need to put it into double curly braces. This tells the template to insert the actual value of the variable right in place.
+
+Run the script again and look at the output. Still not really nice, but at least more readable than the list of tuples. Of course, you can spice-up the very simple HTML markup above, e.g. by using in-line styles to get a better looking output.
+
+
+.. rubric:: Using GET and POST Values
+
+As we can review all open items properly, we move to the next step, which is adding new items to the ToDo list. The new item should be received from a regular HTML-based form, which sends its data by the GET method.
+
+To do so, we first add a new route to our script and tell the route that it should get GET data::
+
+    from bottle import route, run, debug, template, request
+    ...
+    return template('make_table', rows=result)
+    ...
+
+    @route('/new', method='GET')
+    def new_item():
+
+        new = request.GET.get('task', '').strip()
+
+        conn = sqlite3.connect('todo.db')
+        c = conn.cursor()
+
+        c.execute("INSERT INTO todo (task,status) VALUES (?,?)", (new,1))
+        new_id = c.lastrowid
+
+        conn.commit()
+        c.close()
+
+        return '<p>The new task was inserted into the database, the ID is %s</p>' % new_id
+
+To access GET (or POST) data, we need to import ``request`` from Bottle. To assign the actual data to a variable, we use the statement ``request.GET.get('task','').strip()`` statement, where ``task`` is the name of the GET data we want to access. That's all. If your GET data has more than one variable, multiple ``request.GET.get()`` statements can be used and assigned to other variables.
+
+The rest of this piece of code is just processing of the gained data: writing to the database, retrieve the corresponding id from the database and generate the output.
+
+But where do we get the GET data from? Well, we can use a static HTML page holding the form. Or, what we do right now, is to use a template which is output when the route ``/new`` is called without GET data.
+
+The code needs to be extended to::
+
+    ...
+    @route('/new', method='GET')
+    def new_item():
+
+        if request.GET.get('save','').strip():
+
+            new = request.GET.get('task', '').strip()
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+
+            c.execute("INSERT INTO todo (task,status) VALUES (?,?)", (new,1))
+            new_id = c.lastrowid
+
+            conn.commit()
+            c.close()
+
+            return '<p>The new task was inserted into the database, the ID is %s</p>' % new_id
+        else:
+            return template('new_task.tpl')
+
+
+``new_task.tpl`` looks like this::
+
+    <p>Add a new task to the ToDo list:</p>
+    <form action="/new" method="GET">
+    <input type="text" size="100" maxlength="100" name="task">
+    <input type="submit" name="save" value="save">
+    </form>
+
+That's all. As you can see, the template is plain HTML this time.
+
+Now we are able to extend our to do list.
+
+By the way, if you prefer to use POST data: this works exactly the same way, just use ``request.POST.get()`` instead.
+
+
+.. rubric:: Editing Existing Items
+
+The last point to do is to enable editing of existing items.
+
+By using only the routes we know so far it is possible, but may be quite tricky. But Bottle knows something called "dynamic routes", which makes this task quite easy.
+
+The basic statement for a dynamic route looks like this::
+
+    @route('/myroute/:something')
+
+The key point here is the colon. This tells Bottle to accept for ``:something`` any string up to the next slash. Furthermore, the value of ``something`` will be passed to the function assigned to that route, so the data can be processed within the function.
+
+For our ToDo list, we will create a route ``@route('/edit/:no)``, where ``no`` is the id of the item to edit.
+
+The code looks like this::
+
+    @route('/edit/:no', method='GET')
+    def edit_item(no):
+
+        if request.GET.get('save','').strip():
+            edit = request.GET.get('task','').strip()
+            status = request.GET.get('status','').strip()
+
+            if status == 'open':
+                status = 1
+            else:
+                status = 0
+
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+            c.execute("UPDATE todo SET task = ?, status = ? WHERE id LIKE ?", (edit, status, no))
+            conn.commit()
+
+            return '<p>The item number %s was successfully updated</p>' % no
+        else:
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+            c.execute("SELECT task FROM todo WHERE id LIKE ?", (str(no)))
+            cur_data = c.fetchone()
+
+            return template('edit_task', old=cur_data, no=no)
+
+It is basically pretty much the same what we already did above when adding new items, like using ``GET`` data etc. The main addition here is using the dynamic route ``:no``, which here passes the number to the corresponding function. As you can see, ``no`` is used within the function to access the right row of data within the database.
+
+The template ``edit_task.tpl`` called within the function looks like this::
+
+    %#template for editing a task
+    %#the template expects to receive a value for "no" as well a "old", the text of the selected ToDo item
+    <p>Edit the task with ID = {{no}}</p>
+    <form action="/edit/{{no}}" method="get">
+    <input type="text" name="task" value="{{old[0]}}" size="100" maxlength="100">
+    <select name="status">
+    <option>open</option>
+    <option>closed</option>
+    </select>
+    <br/>
+    <input type="submit" name="save" value="save">
+    </form>
+
+Again, this template is a mix of Python statements and HTML, as already explained above.
+
+A last word on dynamic routes: you can even use a regular expression for a dynamic route, as demonstrated later.
+
+
+.. rubric:: Validating Dynamic Routes
+
+Using dynamic routes is fine, but for many cases it makes sense to validate the dynamic part of the route. For example, we expect an integer number in our route for editing above. But if a float, characters or so are received, the Python interpreter throws an exception, which is not what we want.
+
+For those cases, Bottle offers the ``@validate`` decorator, which validates the "input" prior to passing it to the function. In order to apply the validator, extend the code as follows::
+
+    from bottle import route, run, debug, template, request, validate
+    ...
+    @route('/edit/:no', method='GET')
+    @validate(no=int)
+    def edit_item(no):
+    ...
+
+At first, we imported ``validate`` from the Bottle framework, than we apply the @validate-decorator. Right here, we validate if ``no`` is an integer. Basically, the validation works with all types of data like floats, lists etc.
+
+Save the code and call the page again using a "403 forbidden" value for ``:no``, e.g. a float. You will receive not an exception, but a "403 - Forbidden" error, saying that an integer was expected.
+
+.. rubric:: Dynamic Routes Using Regular Expressions
+
+Bottle can also handle dynamic routes, where the "dynamic part" of the route can be a regular expression.
+
+So, just to demonstrate that, let's assume that all single items in our ToDo list should be accessible by their plain number, by a term like e.g. "item1". For obvious reasons, you do not want to create a route for every item. Furthermore, the simple dynamic routes do not work either, as part of the route, the term "item" is static.
+
+As said above, the solution is a regular expression::
+
+    @route('/item:item#[1-9]+#')
+    def show_item(item):
+        conn = sqlite3.connect('todo.db')
+        c = conn.cursor()
+        c.execute("SELECT task FROM todo WHERE id LIKE ?", (item))
+        result = c.fetchall()
+        c.close()
+        if not result:
+            return 'This item number does not exist!'
+        else:
+            return 'Task: %s' %result[0]
+
+Of course, this example is somehow artificially constructed - it would be easier to use a plain dynamic route only combined with a validation. Nevertheless, we want to see how regular expression routes work: the line ``@route(/item:item_#[1-9]+#)`` starts like a normal route, but the part surrounded by # is interpreted as a regular expression, which is the dynamic part of the route. So in this case, we want to match any digit between 0 and 9. The following function "show_item" just checks whether the given item is present in the database or not. In case it is present, the corresponding text of the task is returned. As you can see, only the regular expression part of the route is passed forward. Furthermore, it is always forwarded as a string, even if it is a plain integer number, like in this case.
+
+
+.. rubric:: Returning Static Files
+
+Sometimes it may become necessary to associate a route not to a Python function, but just return a static file. So if you have for example a help page for your application, you may want to return this page as plain HTML. This works as follows::
+
+    from bottle import route, run, debug, template, request, validate, static_file
+
+    @route('/help')
+    def help():
+        return static_file('help.html', root='/path/to/file')
+
+At first, we need to import the ``static_file`` function from Bottle. As you can see, the ``return static_file`` statement replaces the ``return`` statement. It takes at least two arguments: the name of the file to be returned and the path to the file. Even if the file is in the same directory as your application, the path needs to be stated. But in this case, you can use ``'.'`` as a path, too. Bottle guesses the MIME-type of the file automatically, but in case you like to state it explicitly, add a third argument to ``static_file``, which would be here ``mimetype='text/html'``. ``static_file`` works with any type of route, including the dynamic ones.
+
+
+.. rubric:: Returning JSON Data
+
+There may be cases where you do not want your application to generate the output directly, but return data to be processed further on, e.g. by JavaScript. For those cases, Bottle offers the possibility to return JSON objects, which is sort of standard for exchanging data between web applications. Furthermore, JSON can be processed by many programming languages, including Python
+
+So, let's assume we want to return the data generated in the regular expression route example as a JSON object. The code looks like this::
+
+    @route('/json:json#[1-9]+#')
+    def show_json(json):
+        conn = sqlite3.connect('todo.db')
+        c = conn.cursor()
+        c.execute("SELECT task FROM todo WHERE id LIKE ?", (json))
+        result = c.fetchall()
+        c.close()
+
+        if not result:
+            return {'task':'This item number does not exist!'}
+        else:
+            return {'Task': result[0]}
+
+As you can, that is fairly simple: just return a regular Python dictionary and Bottle will convert it automatically into a JSON object prior to sending. So if you e.g. call "http://localhost/json1" Bottle should in this case return the JSON object ``{"Task": ["Read A-byte-of-python to get a good introduction into Python"]}``.
+
+
+
+.. rubric:: Catching Errors
+
+The next step may is to catch the error with Bottle itself, to keep away any type of error message from the user of your application. To do that, Bottle has an "error-route", which can be a assigned to a HTML-error.
+
+In our case, we want to catch a 403 error. The code is as follows::
+
+    from bottle import error
+
+    @error(403)
+    def mistake(code):
+        return 'The parameter you passed has the wrong format!'
+
+So, at first we need to import ``error`` from Bottle and define a route by ``error(403)``, which catches all "403 forbidden" errors. The function "mistake" is assigned to that. Please note that ``error()`` always passes the error-code to the function - even if you do not need it. Thus, the function always needs to accept one argument, otherwise it will not work.
+
+Again, you can assign more than one error-route to a function, or catch various errors with one function each. So this code::
+
+    @error(404)
+    @error(403)
+    def mistake(code):
+        return 'There is something wrong!'
+
+works fine, the following one as well::
+
+    @error(403)
+    def mistake403(code):
+        return 'The parameter you passed has the wrong format!'
+
+    @error(404)
+    def mistake404(code):
+        return 'Sorry, this page does not exist!'
+
+
+.. rubric:: Summary
+
+After going through all the sections above, you should have a brief understanding how the Bottle WSGI framework works. Furthermore you have all the knowledge necessary to use Bottle for your applications.
+
+The following chapter give a short introduction how to adapt Bottle for larger projects. Furthermore, we will show how to operate Bottle with web servers which perform better on a higher load / more web traffic than the one we used so far.
+
+Server Setup
+================================
+
+So far, we used the standard server used by Bottle, which is the `WSGI reference Server`_ shipped along with Python. Although this server is perfectly suitable for development purposes, it is not really suitable for larger applications. But before we have a look at the alternatives, let's have a look how to tweak the settings of the standard server first.
+
+
+.. rubric:: Running Bottle on a different port and IP
+
+As standard, Bottle serves the pages on the IP adress 127.0.0.1, also known as ``localhost``, and on port ``8080``. To modify the setting is pretty simple, as additional parameters can be passed to Bottle's ``run()`` function to change the port and the address.
+
+To change the port, just add ``port=portnumber`` to the run command. So, for example::
+
+    run(port=80)
+
+would make Bottle listen to port 80.
+
+To change the IP address where Bottle is listening::
+
+    run(host='123.45.67.89')
+
+Of course, both parameters can be combined, like::
+
+   run(port=80, host='123.45.67.89')
+
+The ``port`` and ``host`` parameter can also be applied when Bottle is running with a different server, as shown in the following section.
+
+
+.. rubric:: Running Bottle with a different server
+
+As said above, the standard server is perfectly suitable for development, personal use or a small group of people only using your application based on Bottle. For larger tasks, the standard server may become a bottleneck, as it is single-threaded, thus it can only serve one request at a time.
+
+But Bottle has already various adapters to multi-threaded servers on board, which perform better on higher load. Bottle supports Cherrypy_, Fapws3_, Flup_ and Paste_.
+
+If you want to run for example Bottle with the Paste server, use the following code::
+
+    from bottle import PasteServer
+    ...
+    run(server=PasteServer)
+
+This works exactly the same way with ``FlupServer``, ``CherryPyServer`` and ``FapwsServer``.
+
+
+.. rubric:: Running Bottle on Apache with mod_wsgi
+
+Maybe you already have an Apache_ or you want to run a Bottle-based application large scale - then it is time to think about Apache with mod_wsgi_.
+
+We assume that your Apache server is up and running and mod_wsgi is working fine as well. On a lot of Linux distributions, mod_wsgi can be easily installed via whatever package management system is in use.
+
+Bottle brings an adapter for mod_wsgi with it, so serving your application is an easy task.
+
+In the following example, we assume that you want to make your application "ToDo list" accessible through ``http://www.mypage.com/todo`` and your code, templates and SQLite database are stored in the path ``/var/www/todo``.
+
+When you run your application via mod_wsgi, it is imperative to remove the ``run()`` statement from your code, otherwise it won't work here.
+
+After that, create a file called ``adapter.wsgi`` with the following content::
+
+    import sys, os, bottle
+
+    sys.path = ['/var/www/todo/'] + sys.path
+    os.chdir(os.path.dirname(__file__))
+
+    import todo # This loads your application
+
+    application = bottle.default_app()
+
+and save it in the same path, ``/var/www/todo``. Actually the name of the file can be anything, as long as the extension is ``.wsgi``. The name is only used to reference the file from your virtual host.
+
+Finally, we need to add a virtual host to the Apache configuration, which looks like this::
+
+    <VirtualHost *>
+        ServerName mypage.com
+
+        WSGIDaemonProcess todo user=www-data group=www-data processes=1 threads=5
+        WSGIScriptAlias / /var/www/todo/adapter.wsgi
+
+        <Directory /var/www/todo>
+            WSGIProcessGroup todo
+            WSGIApplicationGroup %{GLOBAL}
+            Order deny,allow
+            Allow from all
+        </Directory>
+    </VirtualHost>
+
+After restarting the server, your ToDo list should be accessible at ``http://www.mypage.com/todo``
+
+Final Words
+=========================
+
+Now we are at the end of this introduction and tutorial to Bottle. We learned about the basic concepts of Bottle and wrote a first application using the Bottle framework. In addition to that, we saw how to adapt Bottle for large tasks and serve Bottle through an Apache web server with mod_wsgi.
+
+As said in the introduction, this tutorial is not showing all shades and possibilities of Bottle. What we skipped here is e.g. receiving file objects and streams and how to handle authentication data. Furthermore, we did not show how templates can be called from within another template. For an introduction into those points, please refer to the full `Bottle documentation`_ .
+
+Complete Example Listing
+=========================
+
+As the ToDo list example was developed piece by piece, here is the complete listing:
+
+Main code for the application ``todo.py``::
+
+    import sqlite3
+    from bottle import route, run, debug, template, request, validate, static_file, error
+
+    # only needed when you run Bottle on mod_wsgi
+    from bottle import default_app
+
+    @route('/todo')
+    def todo_list():
+
+        conn = sqlite3.connect('todo.db')
+        c = conn.cursor()
+        c.execute("SELECT id, task FROM todo WHERE status LIKE '1';")
+        result = c.fetchall()
+        c.close()
+
+        output = template('make_table', rows=result)
+        return output
+
+    @route('/new', method='GET')
+    def new_item():
+
+        if request.GET.get('save','').strip():
+
+            new = request.GET.get('task', '').strip()
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+
+            c.execute("INSERT INTO todo (task,status) VALUES (?,?)", (new,1))
+            new_id = c.lastrowid
+
+            conn.commit()
+            c.close()
+
+            return '<p>The new task was inserted into the database, the ID is %s</p>' % new_id
+
+        else:
+            return template('new_task.tpl')
+
+    @route('/edit/:no', method='GET')
+    @validate(no=int)
+    def edit_item(no):
+
+        if request.GET.get('save','').strip():
+            edit = request.GET.get('task','').strip()
+            status = request.GET.get('status','').strip()
+
+            if status == 'open':
+                status = 1
+            else:
+                status = 0
+
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+            c.execute("UPDATE todo SET task = ?, status = ? WHERE id LIKE ?", (edit,status,no))
+            conn.commit()
+
+            return '<p>The item number %s was successfully updated</p>' %no
+
+        else:
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+            c.execute("SELECT task FROM todo WHERE id LIKE ?", (str(no)))
+            cur_data = c.fetchone()
+
+            return template('edit_task', old = cur_data, no = no)
+
+    @route('/item:item#[1-9]+#')
+    def show_item(item):
+
+            conn = sqlite3.connect('todo.db')
+            c = conn.cursor()
+            c.execute("SELECT task FROM todo WHERE id LIKE ?", (item))
+            result = c.fetchall()
+            c.close()
+
+            if not result:
+                return 'This item number does not exist!'
+            else:
+                return 'Task: %s' %result[0]
+
+    @route('/help')
+    def help():
+
+        static_file('help.html', root='.')
+
+    @route('/json:json#[1-9]+#')
+    def show_json(json):
+
+        conn = sqlite3.connect('todo.db')
+        c = conn.cursor()
+        c.execute("SELECT task FROM todo WHERE id LIKE ?", (json))
+        result = c.fetchall()
+        c.close()
+
+        if not result:
+            return {'task':'This item number does not exist!'}
+        else:
+            return {'Task': result[0]}
+
+
+    @error(403)
+    def mistake403(code):
+        return 'There is a mistake in your url!'
+
+    @error(404)
+    def mistake404(code):
+        return 'Sorry, this page does not exist!'
+
+
+    debug(True)
+    run(reloader=True)
+    #remember to remove reloader=True and debug(True) when you move your application from development to a productive environment
+
+Template ``make_table.tpl``::
+
+    %#template to generate a HTML table from a list of tuples (or list of lists, or tuple of tuples or ...)
+    <p>The open items are as follows:</p>
+    <table border="1">
+    %for row in rows:
+      <tr>
+      %for col in row:
+        <td>{{col}}</td>
+      %end
+      </tr>
+    %end
+    </table>
+
+Template ``edit_task.tpl``::
+
+    %#template for editing a task
+    %#the template expects to receive a value for "no" as well a "old", the text of the selected ToDo item
+    <p>Edit the task with ID = {{no}}</p>
+    <form action="/edit/{{no}}" method="get">
+    <input type="text" name="task" value="{{old[0]}}" size="100" maxlength="100">
+    <select name="status">
+    <option>open</option>
+    <option>closed</option>
+    </select>
+    <br/>
+    <input type="submit" name="save" value="save">
+    </form>
+
+Template ``new_task.tpl``::
+
+    %#template for the form for a new task
+    <p>Add a new task to the ToDo list:</p>
+    <form action="/new" method="GET">
+    <input type="text" size="100" maxlength="100" name="task">
+    <input type="submit" name="save" value="save">
+    </form>
diff --git a/html/_static/ajax-loader.gif b/html/_static/ajax-loader.gif
new file mode 100644 (file)
index 0000000..61faf8c
Binary files /dev/null and b/html/_static/ajax-loader.gif differ
diff --git a/html/_static/basic.css b/html/_static/basic.css
new file mode 100644 (file)
index 0000000..43e8baf
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * basic.css
+ * ~~~~~~~~~
+ *
+ * Sphinx stylesheet -- basic theme.
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+    clear: both;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+    width: 100%;
+    font-size: 90%;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+    margin: 0;
+    padding: 0 0 0 10px;
+    list-style: none;
+}
+
+div.related li {
+    display: inline;
+}
+
+div.related li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+    padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+    float: left;
+    width: 230px;
+    margin-left: -100%;
+    font-size: 90%;
+}
+
+div.sphinxsidebar ul {
+    list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+    margin-left: 20px;
+    list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+    margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+    width: 170px;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+    width: 30px;
+}
+
+img {
+    border: 0;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+    margin: 10px 0 0 20px;
+    padding: 0;
+}
+
+ul.search li {
+    padding: 5px 0 5px 20px;
+    background-image: url(file.png);
+    background-repeat: no-repeat;
+    background-position: 0 7px;
+}
+
+ul.search li a {
+    font-weight: bold;
+}
+
+ul.search li div.context {
+    color: #888;
+    margin: 2px 0 0 30px;
+    text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+    font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.3em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+    font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+    width: 100%;
+}
+
+table.indextable td {
+    text-align: left;
+    vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+    height: 10px;
+}
+
+table.indextable tr.cap {
+    margin-top: 10px;
+    background-color: #f2f2f2;
+}
+
+img.toggler {
+    margin-right: 3px;
+    margin-top: 3px;
+    cursor: pointer;
+}
+
+div.modindex-jumpbox {
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    margin: 1em 0 1em 0;
+    padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    margin: 1em 0 1em 0;
+    padding: 0.4em;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+a.headerlink {
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+    visibility: visible;
+}
+
+div.body p.caption {
+    text-align: inherit;
+}
+
+div.body td {
+    text-align: left;
+}
+
+.field-list ul {
+    padding-left: 1em;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+p.rubric {
+    margin-top: 30px;
+    font-weight: bold;
+}
+
+img.align-left, .figure.align-left, object.align-left {
+    clear: left;
+    float: left;
+    margin-right: 1em;
+}
+
+img.align-right, .figure.align-right, object.align-right {
+    clear: right;
+    float: right;
+    margin-left: 1em;
+}
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+    text-align: left;
+}
+
+.align-center {
+    text-align: center;
+}
+
+.align-right {
+    text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+    margin: 0 0 0.5em 1em;
+    border: 1px solid #ddb;
+    padding: 7px 7px 0 7px;
+    background-color: #ffe;
+    width: 40%;
+    float: right;
+}
+
+p.sidebar-title {
+    font-weight: bold;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+div.topic {
+    border: 1px solid #ccc;
+    padding: 7px 7px 0 7px;
+    margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+    font-size: 1.1em;
+    font-weight: bold;
+    margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    padding: 7px;
+}
+
+div.admonition dt {
+    font-weight: bold;
+}
+
+div.admonition dl {
+    margin-bottom: 0;
+}
+
+p.admonition-title {
+    margin: 0px 10px 5px 0px;
+    font-weight: bold;
+}
+
+div.body p.centered {
+    text-align: center;
+    margin-top: 25px;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+    border: 0;
+    border-collapse: collapse;
+}
+
+table.docutils td, table.docutils th {
+    padding: 1px 8px 1px 5px;
+    border-top: 0;
+    border-left: 0;
+    border-right: 0;
+    border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+    border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+    border: 0 !important;
+}
+
+th {
+    text-align: left;
+    padding-right: 5px;
+}
+
+table.citation {
+    border-left: solid 1px gray;
+    margin-left: 1px;
+}
+
+table.citation td {
+    border-bottom: none;
+}
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+    list-style: decimal;
+}
+
+ol.loweralpha {
+    list-style: lower-alpha;
+}
+
+ol.upperalpha {
+    list-style: upper-alpha;
+}
+
+ol.lowerroman {
+    list-style: lower-roman;
+}
+
+ol.upperroman {
+    list-style: upper-roman;
+}
+
+dl {
+    margin-bottom: 15px;
+}
+
+dd p {
+    margin-top: 0px;
+}
+
+dd ul, dd table {
+    margin-bottom: 10px;
+}
+
+dd {
+    margin-top: 3px;
+    margin-bottom: 10px;
+    margin-left: 30px;
+}
+
+dt:target, .highlighted {
+    background-color: #fbe54e;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+.refcount {
+    color: #060;
+}
+
+.optional {
+    font-size: 1.3em;
+}
+
+.versionmodified {
+    font-style: italic;
+}
+
+.system-message {
+    background-color: #fda;
+    padding: 5px;
+    border: 3px solid red;
+}
+
+.footnote:target  {
+    background-color: #ffa;
+}
+
+.line-block {
+    display: block;
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+
+.line-block .line-block {
+    margin-top: 0;
+    margin-bottom: 0;
+    margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+    font-family: sans-serif;
+}
+
+.accelerator {
+    text-decoration: underline;
+}
+
+.classifier {
+    font-style: oblique;
+}
+
+abbr, acronym {
+    border-bottom: dotted 1px;
+    cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+    overflow: auto;
+    overflow-y: hidden;  /* fixes display issues on Chrome browsers */
+}
+
+td.linenos pre {
+    padding: 5px 0px;
+    border: 0;
+    background-color: transparent;
+    color: #aaa;
+}
+
+table.highlighttable {
+    margin-left: 0.5em;
+}
+
+table.highlighttable td {
+    padding: 0 0.5em 0 0.5em;
+}
+
+tt.descname {
+    background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+}
+
+tt.descclassname {
+    background-color: transparent;
+}
+
+tt.xref, a tt {
+    background-color: transparent;
+    font-weight: bold;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+    background-color: transparent;
+}
+
+.viewcode-link {
+    float: right;
+}
+
+.viewcode-back {
+    float: right;
+    font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+    margin: -1px -10px;
+    padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+    vertical-align: middle;
+}
+
+div.body div.math p {
+    text-align: center;
+}
+
+span.eqno {
+    float: right;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+    div.document,
+    div.documentwrapper,
+    div.bodywrapper {
+        margin: 0 !important;
+        width: 100%;
+    }
+
+    div.sphinxsidebar,
+    div.related,
+    div.footer,
+    #top-link {
+        display: none;
+    }
+}
\ No newline at end of file
diff --git a/html/_static/bgrad.png b/html/_static/bgrad.png
new file mode 100644 (file)
index 0000000..82da064
Binary files /dev/null and b/html/_static/bgrad.png differ
diff --git a/html/_static/bottle.css b/html/_static/bottle.css
new file mode 100644 (file)
index 0000000..63dde66
--- /dev/null
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+@import url("basic.css");
+
+/* Positional Layout */
+
+body {
+  width: 940px;
+  margin: 0 auto 0 auto;
+  padding: 15px;
+}
+
+div.document {
+}
+
+div.documentwrapper {
+  float: left;
+  width: 100%;
+}
+
+div.bodywrapper {
+  margin: 0 0 0 230px;
+}
+
+div.sphinxsidebar {
+  width: 230px;
+}
+
+div.sphinxsidebarwrapper {
+  margin: 0 15px;
+  padding: 0;
+}
+
+div.related {
+  line-height: 30px;
+  display: none;
+}
+
+/* Design and Colors */
+
+body {
+  background-color: #E8EFEF;
+  font-family: 'Veranda', sans-serif;
+  font-size: 16px;
+}
+
+div.body {
+  border: 1px solid #697983;
+  background-color: #ffffff;
+  padding: 0 15px 15px 15px;
+  color: #111;
+  line-height: 1.4em;
+}
+
+div.body h2 {
+  background-color: #697983;
+  color: #fff;
+  margin: 2em -15px 1em -30px;
+  padding: 7px 15px 5px 15px;
+  border-top-left-radius: 15px;
+  -moz-border-radius-topleft: 15px;
+  -webkit-border-top-left-radius: 15px;
+  border-bottom-left-radius: 15px;
+  -moz-border-radius-bottomleft: 15px;
+  -webkit-border-bottom-left-radius: 15px;
+}
+
+div.body h3 {
+  margin: 2em 0 1em 0;
+}
+
+div.body h2 a {
+  color: white;
+}
+
+a {
+  color: #005566;
+  text-decoration: none;
+}
+
+a:hover {
+  color: black;
+  text-decoration: underline;
+}
+
+/* Notes and Codes */
+
+pre {
+  background-color: #E8EFEF;
+  margin: 1em 2em;
+  padding: 0.5em;
+}
+
+dd pre, dd div.admonition {
+  margin: 1em 0;
+  padding: 5px 5px;
+  border: 1px solid #ccc;
+}
+
+div.admonition p.last {
+  margin-bottom: 0;
+}
+
+div.admonition {
+  border: 1px solid #697983;
+  margin: 1em 2em;
+  padding: 0.5em;
+  font-size: 0.9em;
+  line-height: 1.3em;
+}
+
+div.admonition p.admonition-title {
+  margin: 0;
+}
+
+div.admonition p.admonition-title:after {
+  content:":";
+}
+
+div.warning {
+  background-color: #fee;
+}
+
+div.note {
+  background-color: #ffc;
+}
+
+div.highlight {
+  background: transparent;
+}
+
+pre {
+  font-size: 12px;
+  line-height: 1.2em;
+}
+
+code, tt.docutils {
+  font-size: 0.9em;
+  padding: 0 0.2em;
+}
+
+tt.xref {
+  border: 0 !important;
+  background-color: transparent !important;
+}
+
+/* Misc */
+
+img.floatright {
+  float: right;
+  margin: 0.5em 1em;
+}
+
+div.body {
+  border-radius: 10px;
+  -moz-border-radius: 10px;
+  -webkit-border-radius: 10px;
+}
+
+div.sphinxsidebar ul {
+  margin: 15px 0;
+  padding: 0 0 0.5em 0;
+  color: #000;
+}
+
+div.sphinxsidebar li {
+  line-height: 1.3em;
+}
+
+div.sphinxsidebar ul ul ul {
+  font-size: 0.9em;
+}
+
+div.sphinxsidebar h3 {
+  background-color: #697983;
+  color: #fff;
+  margin: 0 -15px 0 -5px;
+  padding: 3px 10px 1px 10px;
+  border-top-left-radius: 10px;
+  -moz-border-radius-topleft: 10px;
+  -webkit-border-top-left-radius: 10px;
+  border-bottom-left-radius: 10px;
+  -moz-border-radius-bottomleft: 10px;
+  -webkit-border-bottom-left-radius: 10px;
+}
+
+div.sphinxsidebar a {
+  color: #002a32;
+}
+
+div.sphinxsidebar h3 a {
+  color: white;
+}
+
+div.sphinxsidebar ul ul {
+  list-style: disc outside none;
+}
+
+div.sphinxsidebar input {
+  border: 1px solid grey;
+}
+
+div.sphinxsidebar input:hover {
+  border: 1px solid black;
+}
+
+div.sphinxsidebar input:focus {
+  border: 1px solid black;
+}
+
+div.footer {
+  text-align: center;
+  font-size: 75%;
+  padding: 1em;
+  opacity: 0.5;
+}
+
+/* Fancy Legend  */
+
+.sidelegend {
+  position: fixed;
+  overflow: hidden;
+  font-size: small;
+  background: url('link_icon.png') no-repeat 5px center;
+  padding: 0px 0px 0px 20px;
+}
+
+.sidelegend a {
+  border-top-left-radius: 10px;
+  -moz-border-radius-topleft: 10px;
+  -webkit-border-top-left-radius: 10px;
+  border-bottom-left-radius: 10px;
+  -moz-border-radius-bottomleft: 10px;
+  -webkit-border-bottom-left-radius: 10px;
+  padding: 2px 10px 2px 10px;
+  background: #697983;
+  color: white;
+  display: block;
+}
+
+.sidelegend a:hover {
+  text-decoration: none;
+}
\ No newline at end of file
diff --git a/html/_static/browser-example.png b/html/_static/browser-example.png
new file mode 100644 (file)
index 0000000..d8c3900
Binary files /dev/null and b/html/_static/browser-example.png differ
diff --git a/html/_static/comment-bright.png b/html/_static/comment-bright.png
new file mode 100644 (file)
index 0000000..551517b
Binary files /dev/null and b/html/_static/comment-bright.png differ
diff --git a/html/_static/comment-close.png b/html/_static/comment-close.png
new file mode 100644 (file)
index 0000000..09b54be
Binary files /dev/null and b/html/_static/comment-close.png differ
diff --git a/html/_static/comment.png b/html/_static/comment.png
new file mode 100644 (file)
index 0000000..92feb52
Binary files /dev/null and b/html/_static/comment.png differ
diff --git a/html/_static/default.css b/html/_static/default.css
new file mode 100644 (file)
index 0000000..21f3f50
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * default.css_t
+ * ~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- default theme.
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+    font-family: sans-serif;
+    font-size: 100%;
+    background-color: #11303d;
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+div.document {
+    background-color: #1c4e63;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+div.body {
+    background-color: #ffffff;
+    color: #000000;
+    padding: 0 20px 30px 20px;
+}
+
+div.footer {
+    color: #ffffff;
+    width: 100%;
+    padding: 9px 0 9px 0;
+    text-align: center;
+    font-size: 75%;
+}
+
+div.footer a {
+    color: #ffffff;
+    text-decoration: underline;
+}
+
+div.related {
+    background-color: #133f52;
+    line-height: 30px;
+    color: #ffffff;
+}
+
+div.related a {
+    color: #ffffff;
+}
+
+div.sphinxsidebar {
+}
+
+div.sphinxsidebar h3 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: #ffffff;
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+    color: #ffffff;
+}
+
+div.sphinxsidebar h4 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: #ffffff;
+    font-size: 1.3em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+}
+
+div.sphinxsidebar p {
+    color: #ffffff;
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    padding: 0;
+    color: #ffffff;
+}
+
+div.sphinxsidebar a {
+    color: #98dbcc;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+
+
+/* -- hyperlink styles ------------------------------------------------------ */
+
+a {
+    color: #355f7c;
+    text-decoration: none;
+}
+
+a:visited {
+    color: #355f7c;
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+
+
+/* -- body styles ----------------------------------------------------------- */
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: 'Trebuchet MS', sans-serif;
+    background-color: #f2f2f2;
+    font-weight: normal;
+    color: #20435c;
+    border-bottom: 1px solid #ccc;
+    margin: 20px -20px 10px -20px;
+    padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 160%; }
+div.body h3 { font-size: 140%; }
+div.body h4 { font-size: 120%; }
+div.body h5 { font-size: 110%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+    color: #c60f0f;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+}
+
+a.headerlink:hover {
+    background-color: #c60f0f;
+    color: white;
+}
+
+div.body p, div.body dd, div.body li {
+    text-align: justify;
+    line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+    display: inline;
+}
+
+div.admonition p {
+    margin-bottom: 5px;
+}
+
+div.admonition pre {
+    margin-bottom: 5px;
+}
+
+div.admonition ul, div.admonition ol {
+    margin-bottom: 5px;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+
+div.topic {
+    background-color: #eee;
+}
+
+div.warning {
+    background-color: #ffe4e4;
+    border: 1px solid #f66;
+}
+
+p.admonition-title {
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+pre {
+    padding: 5px;
+    background-color: #eeffcc;
+    color: #333333;
+    line-height: 120%;
+    border: 1px solid #ac9;
+    border-left: none;
+    border-right: none;
+}
+
+tt {
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}
+
+th {
+    background-color: #ede;
+}
+
+.warning tt {
+    background: #efc2c2;
+}
+
+.note tt {
+    background: #d6d6d6;
+}
+
+.viewcode-back {
+    font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+    background-color: #f4debf;
+    border-top: 1px solid #ac9;
+    border-bottom: 1px solid #ac9;
+}
\ No newline at end of file
diff --git a/html/_static/default.js b/html/_static/default.js
new file mode 100644 (file)
index 0000000..cfe9dea
--- /dev/null
@@ -0,0 +1,137 @@
+// Awesome scrollbar navigaion
+
+POI = function(anchor, title, options) {
+    // Create a Point-Of-Interest, a named position within the document.
+    // @param anchor is the point of interest (HTML or jquery node). This MUST
+    //        have an ID attribute.
+    // @param title is the name of the POI (string)
+    POI.all.push(this);
+    
+    //: Number of pixels the handle should be visible
+    options = options || {};
+    this.peak = options.peak || POI.peak;
+    this.delay = options.delay || POI.delay;
+    this.css = options.css || POI.css;
+
+    this.pinned = false;
+    this.visible = false;
+    this.hide_timeout = null;
+
+    this.anchor = $(anchor);
+    this.id = this.anchor.attr('id');
+    this.title = title || $(anchor).text();
+    this.node  = $('<div>').addClass(this.css).appendTo('body');
+    this.link  = $('<a>').text(this.title)
+                         .attr('href', '#'+this.id)
+                         .appendTo(this.node);
+    this.node.css('right', '-'+(this.node.outerWidth()-this.peak)+'px');
+    this.refresh();
+    this.node.mouseenter(function() { POI.show(); });
+    this.node.mouseleave(function() { POI.hide(POI.delay); });
+}
+
+POI.prototype.refresh = function() {
+    // Re-arrange the anchors
+    var dsize = $(document).height();
+    var wsize = $(window).height();
+    var pos = this.anchor.offset().top;
+    var hpos = Math.round(wsize*(pos/dsize));
+    this.node.css('top', hpos+'px');
+}
+
+POI.prototype.show = function() {
+    // Show the handle
+    if(this.visible) return;
+    this.node.stop(true).animate({'right': '0px'}, 250);
+    this.visible = true;
+}
+
+POI.prototype.hide = function() {
+    // Hide the handle
+    if(this.pinned) return;
+    if(! this.visible) return;
+    this.node.stop(true).animate({
+        'right': '-'+(this.node.outerWidth()-this.peak)+'px'
+    }, 250);
+    this.visible = false;
+}
+
+
+
+// Static attributes and methods.
+
+POI.all = Array();
+POI.peak = 20;
+POI.delay = 2000;
+POI.css = 'sidelegend';
+POI.hide_timeout = null;
+
+POI.refresh = function() {
+    // Refresh all at once
+    jQuery.each(POI.all, function() {
+        this.refresh();
+    })
+}
+
+POI.show = function() {
+    // Show all at once
+    if(POI.hide_timeout) window.clearTimeout(POI.hide_timeout);
+    POI.hide_timeout = null;
+    jQuery.each(POI.all, function() {
+        this.show();
+    })
+}
+
+POI.hide = function(delay) {
+    // Hide all at once after a specific delay
+    if(POI.hide_timeout) window.clearTimeout(POI.hide_timeout);
+    if(delay) {
+        POI.hide_timeout = window.setTimeout(function() {
+            POI.hide_timeout = null;
+            POI.hide();
+        }, delay)
+    } else {
+        jQuery.each(POI.all, function() {
+            this.hide();
+        })
+    }
+}
+
+POI.whereami = function() {
+    // Show and pin the currently viewed POI
+    var position = $(window).scrollTop() + $(window).height() / 2;
+    var last = null;
+    jQuery.each(POI.all, function() {
+        if(position < this.anchor.offset().top) return false;
+        last = this;
+    })
+    if(last) {
+        last.pinned = true;
+        last.show();
+    }
+    jQuery.each(POI.all, function() {
+        if(this != last) {
+            this.pinned = false;
+            this.hide();
+        }
+    })
+}
+
+
+
+$(document).resize(POI.refresh);
+$(window).resize(POI.refresh);
+$(window).scroll(POI.whereami);
+
+// Global events that affect all POIs
+$(document).ready(function() {
+    $('.section > h1 > a.headerlink, .section > h2 > a.headerlink').each(function(index){
+        var lnk = $(this);
+        var title = lnk.parent().text().replace('¶','')
+        var anchor = lnk.parent().parent()
+        new POI(anchor, title)
+    })
+    POI.whereami();
+})
+
+
diff --git a/html/_static/doctools.js b/html/_static/doctools.js
new file mode 100644 (file)
index 0000000..d4619fd
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * select a different prefix for underscore
+ */
+$u = _.noConflict();
+
+/**
+ * make the code below compatible with browsers without
+ * an installed firebug like debugger
+if (!window.console || !console.firebug) {
+  var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
+    "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
+    "profile", "profileEnd"];
+  window.console = {};
+  for (var i = 0; i < names.length; ++i)
+    window.console[names[i]] = function() {};
+}
+ */
+
+/**
+ * small helper function to urldecode strings
+ */
+jQuery.urldecode = function(x) {
+  return decodeURIComponent(x).replace(/\+/g, ' ');
+}
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+  if (typeof s == 'undefined')
+    s = document.location.search;
+  var parts = s.substr(s.indexOf('?') + 1).split('&');
+  var result = {};
+  for (var i = 0; i < parts.length; i++) {
+    var tmp = parts[i].split('=', 2);
+    var key = jQuery.urldecode(tmp[0]);
+    var value = jQuery.urldecode(tmp[1]);
+    if (key in result)
+      result[key].push(value);
+    else
+      result[key] = [value];
+  }
+  return result;
+};
+
+/**
+ * small function to check if an array contains
+ * a given item.
+ */
+jQuery.contains = function(arr, item) {
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i] == item)
+      return true;
+  }
+  return false;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+  function highlight(node) {
+    if (node.nodeType == 3) {
+      var val = node.nodeValue;
+      var pos = val.toLowerCase().indexOf(text);
+      if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
+        var span = document.createElement("span");
+        span.className = className;
+        span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+        node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+          document.createTextNode(val.substr(pos + text.length)),
+          node.nextSibling));
+        node.nodeValue = val.substr(0, pos);
+      }
+    }
+    else if (!jQuery(node).is("button, select, textarea")) {
+      jQuery.each(node.childNodes, function() {
+        highlight(this);
+      });
+    }
+  }
+  return this.each(function() {
+    highlight(this);
+  });
+};
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+  init : function() {
+    this.fixFirefoxAnchorBug();
+    this.highlightSearchWords();
+    this.initIndexTable();
+  },
+
+  /**
+   * i18n support
+   */
+  TRANSLATIONS : {},
+  PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
+  LOCALE : 'unknown',
+
+  // gettext and ngettext don't access this so that the functions
+  // can safely bound to a different name (_ = Documentation.gettext)
+  gettext : function(string) {
+    var translated = Documentation.TRANSLATIONS[string];
+    if (typeof translated == 'undefined')
+      return string;
+    return (typeof translated == 'string') ? translated : translated[0];
+  },
+
+  ngettext : function(singular, plural, n) {
+    var translated = Documentation.TRANSLATIONS[singular];
+    if (typeof translated == 'undefined')
+      return (n == 1) ? singular : plural;
+    return translated[Documentation.PLURALEXPR(n)];
+  },
+
+  addTranslations : function(catalog) {
+    for (var key in catalog.messages)
+      this.TRANSLATIONS[key] = catalog.messages[key];
+    this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
+    this.LOCALE = catalog.locale;
+  },
+
+  /**
+   * add context elements like header anchor links
+   */
+  addContextElements : function() {
+    $('div[id] > :header:first').each(function() {
+      $('<a class="headerlink">\u00B6</a>').
+      attr('href', '#' + this.id).
+      attr('title', _('Permalink to this headline')).
+      appendTo(this);
+    });
+    $('dt[id]').each(function() {
+      $('<a class="headerlink">\u00B6</a>').
+      attr('href', '#' + this.id).
+      attr('title', _('Permalink to this definition')).
+      appendTo(this);
+    });
+  },
+
+  /**
+   * workaround a firefox stupidity
+   */
+  fixFirefoxAnchorBug : function() {
+    if (document.location.hash && $.browser.mozilla)
+      window.setTimeout(function() {
+        document.location.href += '';
+      }, 10);
+  },
+
+  /**
+   * highlight the search words provided in the url in the text
+   */
+  highlightSearchWords : function() {
+    var params = $.getQueryParameters();
+    var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
+    if (terms.length) {
+      var body = $('div.body');
+      window.setTimeout(function() {
+        $.each(terms, function() {
+          body.highlightText(this.toLowerCase(), 'highlighted');
+        });
+      }, 10);
+      $('<p class="highlight-link"><a href="javascript:Documentation.' +
+        'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
+          .appendTo($('#searchbox'));
+    }
+  },
+
+  /**
+   * init the domain index toggle buttons
+   */
+  initIndexTable : function() {
+    var togglers = $('img.toggler').click(function() {
+      var src = $(this).attr('src');
+      var idnum = $(this).attr('id').substr(7);
+      $('tr.cg-' + idnum).toggle();
+      if (src.substr(-9) == 'minus.png')
+        $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
+      else
+        $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
+    }).css('display', '');
+    if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
+        togglers.click();
+    }
+  },
+
+  /**
+   * helper function to hide the search marks again
+   */
+  hideSearchWords : function() {
+    $('#searchbox .highlight-link').fadeOut(300);
+    $('span.highlighted').removeClass('highlighted');
+  },
+
+  /**
+   * make the url absolute
+   */
+  makeURL : function(relativeURL) {
+    return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
+  },
+
+  /**
+   * get the current relative url
+   */
+  getCurrentURL : function() {
+    var path = document.location.pathname;
+    var parts = path.split(/\//);
+    $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
+      if (this == '..')
+        parts.pop();
+    });
+    var url = parts.join('/');
+    return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
+  }
+};
+
+// quick alias for translations
+_ = Documentation.gettext;
+
+$(document).ready(function() {
+  Documentation.init();
+});
diff --git a/html/_static/down-pressed.png b/html/_static/down-pressed.png
new file mode 100644 (file)
index 0000000..6f7ad78
Binary files /dev/null and b/html/_static/down-pressed.png differ
diff --git a/html/_static/down.png b/html/_static/down.png
new file mode 100644 (file)
index 0000000..3003a88
Binary files /dev/null and b/html/_static/down.png differ
diff --git a/html/_static/favicon.ico b/html/_static/favicon.ico
new file mode 100644 (file)
index 0000000..b6b83f1
Binary files /dev/null and b/html/_static/favicon.ico differ
diff --git a/html/_static/file.png b/html/_static/file.png
new file mode 100644 (file)
index 0000000..d18082e
Binary files /dev/null and b/html/_static/file.png differ
diff --git a/html/_static/jquery.js b/html/_static/jquery.js
new file mode 100644 (file)
index 0000000..8ccd0ea
--- /dev/null
@@ -0,0 +1,9266 @@
+/*!
+ * jQuery JavaScript Library v1.7.1
+ * http://jquery.com/
+ *
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Mon Nov 21 21:11:03 2011 -0500
+ */
+(function( window, undefined ) {
+
+// Use the correct document accordingly with window argument (sandbox)
+var document = window.document,
+       navigator = window.navigator,
+       location = window.location;
+var jQuery = (function() {
+
+// Define a local copy of jQuery
+var jQuery = function( selector, context ) {
+               // The jQuery object is actually just the init constructor 'enhanced'
+               return new jQuery.fn.init( selector, context, rootjQuery );
+       },
+
+       // Map over jQuery in case of overwrite
+       _jQuery = window.jQuery,
+
+       // Map over the $ in case of overwrite
+       _$ = window.$,
+
+       // A central reference to the root jQuery(document)
+       rootjQuery,
+
+       // A simple way to check for HTML strings or ID strings
+       // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+       quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
+
+       // Check if a string has a non-whitespace character in it
+       rnotwhite = /\S/,
+
+       // Used for trimming whitespace
+       trimLeft = /^\s+/,
+       trimRight = /\s+$/,
+
+       // Match a standalone tag
+       rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
+
+       // JSON RegExp
+       rvalidchars = /^[\],:{}\s]*$/,
+       rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+       rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+       rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
+
+       // Useragent RegExp
+       rwebkit = /(webkit)[ \/]([\w.]+)/,
+       ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
+       rmsie = /(msie) ([\w.]+)/,
+       rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
+
+       // Matches dashed string for camelizing
+       rdashAlpha = /-([a-z]|[0-9])/ig,
+       rmsPrefix = /^-ms-/,
+
+       // Used by jQuery.camelCase as callback to replace()
+       fcamelCase = function( all, letter ) {
+               return ( letter + "" ).toUpperCase();
+       },
+
+       // Keep a UserAgent string for use with jQuery.browser
+       userAgent = navigator.userAgent,
+
+       // For matching the engine and version of the browser
+       browserMatch,
+
+       // The deferred used on DOM ready
+       readyList,
+
+       // The ready event handler
+       DOMContentLoaded,
+
+       // Save a reference to some core methods
+       toString = Object.prototype.toString,
+       hasOwn = Object.prototype.hasOwnProperty,
+       push = Array.prototype.push,
+       slice = Array.prototype.slice,
+       trim = String.prototype.trim,
+       indexOf = Array.prototype.indexOf,
+
+       // [[Class]] -> type pairs
+       class2type = {};
+
+jQuery.fn = jQuery.prototype = {
+       constructor: jQuery,
+       init: function( selector, context, rootjQuery ) {
+               var match, elem, ret, doc;
+
+               // Handle $(""), $(null), or $(undefined)
+               if ( !selector ) {
+                       return this;
+               }
+
+               // Handle $(DOMElement)
+               if ( selector.nodeType ) {
+                       this.context = this[0] = selector;
+                       this.length = 1;
+                       return this;
+               }
+
+               // The body element only exists once, optimize finding it
+               if ( selector === "body" && !context && document.body ) {
+                       this.context = document;
+                       this[0] = document.body;
+                       this.selector = selector;
+                       this.length = 1;
+                       return this;
+               }
+
+               // Handle HTML strings
+               if ( typeof selector === "string" ) {
+                       // Are we dealing with HTML string or an ID?
+                       if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+                               // Assume that strings that start and end with <> are HTML and skip the regex check
+                               match = [ null, selector, null ];
+
+                       } else {
+                               match = quickExpr.exec( selector );
+                       }
+
+                       // Verify a match, and that no context was specified for #id
+                       if ( match && (match[1] || !context) ) {
+
+                               // HANDLE: $(html) -> $(array)
+                               if ( match[1] ) {
+                                       context = context instanceof jQuery ? context[0] : context;
+                                       doc = ( context ? context.ownerDocument || context : document );
+
+                                       // If a single string is passed in and it's a single tag
+                                       // just do a createElement and skip the rest
+                                       ret = rsingleTag.exec( selector );
+
+                                       if ( ret ) {
+                                               if ( jQuery.isPlainObject( context ) ) {
+                                                       selector = [ document.createElement( ret[1] ) ];
+                                                       jQuery.fn.attr.call( selector, context, true );
+
+                                               } else {
+                                                       selector = [ doc.createElement( ret[1] ) ];
+                                               }
+
+                                       } else {
+                                               ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
+                                               selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes;
+                                       }
+
+                                       return jQuery.merge( this, selector );
+
+                               // HANDLE: $("#id")
+                               } else {
+                                       elem = document.getElementById( match[2] );
+
+                                       // Check parentNode to catch when Blackberry 4.6 returns
+                                       // nodes that are no longer in the document #6963
+                                       if ( elem && elem.parentNode ) {
+                                               // Handle the case where IE and Opera return items
+                                               // by name instead of ID
+                                               if ( elem.id !== match[2] ) {
+                                                       return rootjQuery.find( selector );
+                                               }
+
+                                               // Otherwise, we inject the element directly into the jQuery object
+                                               this.length = 1;
+                                               this[0] = elem;
+                                       }
+
+                                       this.context = document;
+                                       this.selector = selector;
+                                       return this;
+                               }
+
+                       // HANDLE: $(expr, $(...))
+                       } else if ( !context || context.jquery ) {
+                               return ( context || rootjQuery ).find( selector );
+
+                       // HANDLE: $(expr, context)
+                       // (which is just equivalent to: $(context).find(expr)
+                       } else {
+                               return this.constructor( context ).find( selector );
+                       }
+
+               // HANDLE: $(function)
+               // Shortcut for document ready
+               } else if ( jQuery.isFunction( selector ) ) {
+                       return rootjQuery.ready( selector );
+               }
+
+               if ( selector.selector !== undefined ) {
+                       this.selector = selector.selector;
+                       this.context = selector.context;
+               }
+
+               return jQuery.makeArray( selector, this );
+       },
+
+       // Start with an empty selector
+       selector: "",
+
+       // The current version of jQuery being used
+       jquery: "1.7.1",
+
+       // The default length of a jQuery object is 0
+       length: 0,
+
+       // The number of elements contained in the matched element set
+       size: function() {
+               return this.length;
+       },
+
+       toArray: function() {
+               return slice.call( this, 0 );
+       },
+
+       // Get the Nth element in the matched element set OR
+       // Get the whole matched element set as a clean array
+       get: function( num ) {
+               return num == null ?
+
+                       // Return a 'clean' array
+                       this.toArray() :
+
+                       // Return just the object
+                       ( num < 0 ? this[ this.length + num ] : this[ num ] );
+       },
+
+       // Take an array of elements and push it onto the stack
+       // (returning the new matched element set)
+       pushStack: function( elems, name, selector ) {
+               // Build a new jQuery matched element set
+               var ret = this.constructor();
+
+               if ( jQuery.isArray( elems ) ) {
+                       push.apply( ret, elems );
+
+               } else {
+                       jQuery.merge( ret, elems );
+               }
+
+               // Add the old object onto the stack (as a reference)
+               ret.prevObject = this;
+
+               ret.context = this.context;
+
+               if ( name === "find" ) {
+                       ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
+               } else if ( name ) {
+                       ret.selector = this.selector + "." + name + "(" + selector + ")";
+               }
+
+               // Return the newly-formed element set
+               return ret;
+       },
+
+       // Execute a callback for every element in the matched set.
+       // (You can seed the arguments with an array of args, but this is
+       // only used internally.)
+       each: function( callback, args ) {
+               return jQuery.each( this, callback, args );
+       },
+
+       ready: function( fn ) {
+               // Attach the listeners
+               jQuery.bindReady();
+
+               // Add the callback
+               readyList.add( fn );
+
+               return this;
+       },
+
+       eq: function( i ) {
+               i = +i;
+               return i === -1 ?
+                       this.slice( i ) :
+                       this.slice( i, i + 1 );
+       },
+
+       first: function() {
+               return this.eq( 0 );
+       },
+
+       last: function() {
+               return this.eq( -1 );
+       },
+
+       slice: function() {
+               return this.pushStack( slice.apply( this, arguments ),
+                       "slice", slice.call(arguments).join(",") );
+       },
+
+       map: function( callback ) {
+               return this.pushStack( jQuery.map(this, function( elem, i ) {
+                       return callback.call( elem, i, elem );
+               }));
+       },
+
+       end: function() {
+               return this.prevObject || this.constructor(null);
+       },
+
+       // For internal use only.
+       // Behaves like an Array's method, not like a jQuery method.
+       push: push,
+       sort: [].sort,
+       splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+       var options, name, src, copy, copyIsArray, clone,
+               target = arguments[0] || {},
+               i = 1,
+               length = arguments.length,
+               deep = false;
+
+       // Handle a deep copy situation
+       if ( typeof target === "boolean" ) {
+               deep = target;
+               target = arguments[1] || {};
+               // skip the boolean and the target
+               i = 2;
+       }
+
+       // Handle case when target is a string or something (possible in deep copy)
+       if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+               target = {};
+       }
+
+       // extend jQuery itself if only one argument is passed
+       if ( length === i ) {
+               target = this;
+               --i;
+       }
+
+       for ( ; i < length; i++ ) {
+               // Only deal with non-null/undefined values
+               if ( (options = arguments[ i ]) != null ) {
+                       // Extend the base object
+                       for ( name in options ) {
+                               src = target[ name ];
+                               copy = options[ name ];
+
+                               // Prevent never-ending loop
+                               if ( target === copy ) {
+                                       continue;
+                               }
+
+                               // Recurse if we're merging plain objects or arrays
+                               if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+                                       if ( copyIsArray ) {
+                                               copyIsArray = false;
+                                               clone = src && jQuery.isArray(src) ? src : [];
+
+                                       } else {
+                                               clone = src && jQuery.isPlainObject(src) ? src : {};
+                                       }
+
+                                       // Never move original objects, clone them
+                                       target[ name ] = jQuery.extend( deep, clone, copy );
+
+                               // Don't bring in undefined values
+                               } else if ( copy !== undefined ) {
+                                       target[ name ] = copy;
+                               }
+                       }
+               }
+       }
+
+       // Return the modified object
+       return target;
+};
+
+jQuery.extend({
+       noConflict: function( deep ) {
+               if ( window.$ === jQuery ) {
+                       window.$ = _$;
+               }
+
+               if ( deep && window.jQuery === jQuery ) {
+                       window.jQuery = _jQuery;
+               }
+
+               return jQuery;
+       },
+
+       // Is the DOM ready to be used? Set to true once it occurs.
+       isReady: false,
+
+       // A counter to track how many items to wait for before
+       // the ready event fires. See #6781
+       readyWait: 1,
+
+       // Hold (or release) the ready event
+       holdReady: function( hold ) {
+               if ( hold ) {
+                       jQuery.readyWait++;
+               } else {
+                       jQuery.ready( true );
+               }
+       },
+
+       // Handle when the DOM is ready
+       ready: function( wait ) {
+               // Either a released hold or an DOMready/load event and not yet ready
+               if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
+                       // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+                       if ( !document.body ) {
+                               return setTimeout( jQuery.ready, 1 );
+                       }
+
+                       // Remember that the DOM is ready
+                       jQuery.isReady = true;
+
+                       // If a normal DOM Ready event fired, decrement, and wait if need be
+                       if ( wait !== true && --jQuery.readyWait > 0 ) {
+                               return;
+                       }
+
+                       // If there are functions bound, to execute
+                       readyList.fireWith( document, [ jQuery ] );
+
+                       // Trigger any bound ready events
+                       if ( jQuery.fn.trigger ) {
+                               jQuery( document ).trigger( "ready" ).off( "ready" );
+                       }
+               }
+       },
+
+       bindReady: function() {
+               if ( readyList ) {
+                       return;
+               }
+
+               readyList = jQuery.Callbacks( "once memory" );
+
+               // Catch cases where $(document).ready() is called after the
+               // browser event has already occurred.
+               if ( document.readyState === "complete" ) {
+                       // Handle it asynchronously to allow scripts the opportunity to delay ready
+                       return setTimeout( jQuery.ready, 1 );
+               }
+
+               // Mozilla, Opera and webkit nightlies currently support this event
+               if ( document.addEventListener ) {
+                       // Use the handy event callback
+                       document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+
+                       // A fallback to window.onload, that will always work
+                       window.addEventListener( "load", jQuery.ready, false );
+
+               // If IE event model is used
+               } else if ( document.attachEvent ) {
+                       // ensure firing before onload,
+                       // maybe late but safe also for iframes
+                       document.attachEvent( "onreadystatechange", DOMContentLoaded );
+
+                       // A fallback to window.onload, that will always work
+                       window.attachEvent( "onload", jQuery.ready );
+
+                       // If IE and not a frame
+                       // continually check to see if the document is ready
+                       var toplevel = false;
+
+                       try {
+                               toplevel = window.frameElement == null;
+                       } catch(e) {}
+
+                       if ( document.documentElement.doScroll && toplevel ) {
+                               doScrollCheck();
+                       }
+               }
+       },
+
+       // See test/unit/core.js for details concerning isFunction.
+       // Since version 1.3, DOM methods and functions like alert
+       // aren't supported. They return false on IE (#2968).
+       isFunction: function( obj ) {
+               return jQuery.type(obj) === "function";
+       },
+
+       isArray: Array.isArray || function( obj ) {
+               return jQuery.type(obj) === "array";
+       },
+
+       // A crude way of determining if an object is a window
+       isWindow: function( obj ) {
+               return obj && typeof obj === "object" && "setInterval" in obj;
+       },
+
+       isNumeric: function( obj ) {
+               return !isNaN( parseFloat(obj) ) && isFinite( obj );
+       },
+
+       type: function( obj ) {
+               return obj == null ?
+                       String( obj ) :
+                       class2type[ toString.call(obj) ] || "object";
+       },
+
+       isPlainObject: function( obj ) {
+               // Must be an Object.
+               // Because of IE, we also have to check the presence of the constructor property.
+               // Make sure that DOM nodes and window objects don't pass through, as well
+               if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+                       return false;
+               }
+
+               try {
+                       // Not own constructor property must be Object
+                       if ( obj.constructor &&
+                               !hasOwn.call(obj, "constructor") &&
+                               !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+                               return false;
+                       }
+               } catch ( e ) {
+                       // IE8,9 Will throw exceptions on certain host objects #9897
+                       return false;
+               }
+
+               // Own properties are enumerated firstly, so to speed up,
+               // if last one is own, then all properties are own.
+
+               var key;
+               for ( key in obj ) {}
+
+               return key === undefined || hasOwn.call( obj, key );
+       },
+
+       isEmptyObject: function( obj ) {
+               for ( var name in obj ) {
+                       return false;
+               }
+               return true;
+       },
+
+       error: function( msg ) {
+               throw new Error( msg );
+       },
+
+       parseJSON: function( data ) {
+               if ( typeof data !== "string" || !data ) {
+                       return null;
+               }
+
+               // Make sure leading/trailing whitespace is removed (IE can't handle it)
+               data = jQuery.trim( data );
+
+               // Attempt to parse using the native JSON parser first
+               if ( window.JSON && window.JSON.parse ) {
+                       return window.JSON.parse( data );
+               }
+
+               // Make sure the incoming data is actual JSON
+               // Logic borrowed from http://json.org/json2.js
+               if ( rvalidchars.test( data.replace( rvalidescape, "@" )
+                       .replace( rvalidtokens, "]" )
+                       .replace( rvalidbraces, "")) ) {
+
+                       return ( new Function( "return " + data ) )();
+
+               }
+               jQuery.error( "Invalid JSON: " + data );
+       },
+
+       // Cross-browser xml parsing
+       parseXML: function( data ) {
+               var xml, tmp;
+               try {
+                       if ( window.DOMParser ) { // Standard
+                               tmp = new DOMParser();
+                               xml = tmp.parseFromString( data , "text/xml" );
+                       } else { // IE
+                               xml = new ActiveXObject( "Microsoft.XMLDOM" );
+                               xml.async = "false";
+                               xml.loadXML( data );
+                       }
+               } catch( e ) {
+                       xml = undefined;
+               }
+               if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+                       jQuery.error( "Invalid XML: " + data );
+               }
+               return xml;
+       },
+
+       noop: function() {},
+
+       // Evaluates a script in a global context
+       // Workarounds based on findings by Jim Driscoll
+       // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+       globalEval: function( data ) {
+               if ( data && rnotwhite.test( data ) ) {
+                       // We use execScript on Internet Explorer
+                       // We use an anonymous function so that context is window
+                       // rather than jQuery in Firefox
+                       ( window.execScript || function( data ) {
+                               window[ "eval" ].call( window, data );
+                       } )( data );
+               }
+       },
+
+       // Convert dashed to camelCase; used by the css and data modules
+       // Microsoft forgot to hump their vendor prefix (#9572)
+       camelCase: function( string ) {
+               return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+       },
+
+       nodeName: function( elem, name ) {
+               return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
+       },
+
+       // args is for internal usage only
+       each: function( object, callback, args ) {
+               var name, i = 0,
+                       length = object.length,
+                       isObj = length === undefined || jQuery.isFunction( object );
+
+               if ( args ) {
+                       if ( isObj ) {
+                               for ( name in object ) {
+                                       if ( callback.apply( object[ name ], args ) === false ) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               for ( ; i < length; ) {
+                                       if ( callback.apply( object[ i++ ], args ) === false ) {
+                                               break;
+                                       }
+                               }
+                       }
+
+               // A special, fast, case for the most common use of each
+               } else {
+                       if ( isObj ) {
+                               for ( name in object ) {
+                                       if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+                                               break;
+                                       }
+                               }
+                       } else {
+                               for ( ; i < length; ) {
+                                       if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               return object;
+       },
+
+       // Use native String.trim function wherever possible
+       trim: trim ?
+               function( text ) {
+                       return text == null ?
+                               "" :
+                               trim.call( text );
+               } :
+
+               // Otherwise use our own trimming functionality
+               function( text ) {
+                       return text == null ?
+                               "" :
+                               text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
+               },
+
+       // results is for internal usage only
+       makeArray: function( array, results ) {
+               var ret = results || [];
+
+               if ( array != null ) {
+                       // The window, strings (and functions) also have 'length'
+                       // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
+                       var type = jQuery.type( array );
+
+                       if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
+                               push.call( ret, array );
+                       } else {
+                               jQuery.merge( ret, array );
+                       }
+               }
+
+               return ret;
+       },
+
+       inArray: function( elem, array, i ) {
+               var len;
+
+               if ( array ) {
+                       if ( indexOf ) {
+                               return indexOf.call( array, elem, i );
+                       }
+
+                       len = array.length;
+                       i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+                       for ( ; i < len; i++ ) {
+                               // Skip accessing in sparse arrays
+                               if ( i in array && array[ i ] === elem ) {
+                                       return i;
+                               }
+                       }
+               }
+
+               return -1;
+       },
+
+       merge: function( first, second ) {
+               var i = first.length,
+                       j = 0;
+
+               if ( typeof second.length === "number" ) {
+                       for ( var l = second.length; j < l; j++ ) {
+                               first[ i++ ] = second[ j ];
+                       }
+
+               } else {
+                       while ( second[j] !== undefined ) {
+                               first[ i++ ] = second[ j++ ];
+                       }
+               }
+
+               first.length = i;
+
+               return first;
+       },
+
+       grep: function( elems, callback, inv ) {
+               var ret = [], retVal;
+               inv = !!inv;
+
+               // Go through the array, only saving the items
+               // that pass the validator function
+               for ( var i = 0, length = elems.length; i < length; i++ ) {
+                       retVal = !!callback( elems[ i ], i );
+                       if ( inv !== retVal ) {
+                               ret.push( elems[ i ] );
+                       }
+               }
+
+               return ret;
+       },
+
+       // arg is for internal usage only
+       map: function( elems, callback, arg ) {
+               var value, key, ret = [],
+                       i = 0,
+                       length = elems.length,
+                       // jquery objects are treated as arrays
+                       isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
+
+               // Go through the array, translating each of the items to their
+               if ( isArray ) {
+                       for ( ; i < length; i++ ) {
+                               value = callback( elems[ i ], i, arg );
+
+                               if ( value != null ) {
+                                       ret[ ret.length ] = value;
+                               }
+                       }
+
+               // Go through every key on the object,
+               } else {
+                       for ( key in elems ) {
+                               value = callback( elems[ key ], key, arg );
+
+                               if ( value != null ) {
+                                       ret[ ret.length ] = value;
+                               }
+                       }
+               }
+
+               // Flatten any nested arrays
+               return ret.concat.apply( [], ret );
+       },
+
+       // A global GUID counter for objects
+       guid: 1,
+
+       // Bind a function to a context, optionally partially applying any
+       // arguments.
+       proxy: function( fn, context ) {
+               if ( typeof context === "string" ) {
+                       var tmp = fn[ context ];
+                       context = fn;
+                       fn = tmp;
+               }
+
+               // Quick check to determine if target is callable, in the spec
+               // this throws a TypeError, but we will just return undefined.
+               if ( !jQuery.isFunction( fn ) ) {
+                       return undefined;
+               }
+
+               // Simulated bind
+               var args = slice.call( arguments, 2 ),
+                       proxy = function() {
+                               return fn.apply( context, args.concat( slice.call( arguments ) ) );
+                       };
+
+               // Set the guid of unique handler to the same of original handler, so it can be removed
+               proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
+
+               return proxy;
+       },
+
+       // Mutifunctional method to get and set values to a collection
+       // The value/s can optionally be executed if it's a function
+       access: function( elems, key, value, exec, fn, pass ) {
+               var length = elems.length;
+
+               // Setting many attributes
+               if ( typeof key === "object" ) {
+                       for ( var k in key ) {
+                               jQuery.access( elems, k, key[k], exec, fn, value );
+                       }
+                       return elems;
+               }
+
+               // Setting one attribute
+               if ( value !== undefined ) {
+                       // Optionally, function values get executed if exec is true
+                       exec = !pass && exec && jQuery.isFunction(value);
+
+                       for ( var i = 0; i < length; i++ ) {
+                               fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
+                       }
+
+                       return elems;
+               }
+
+               // Getting an attribute
+               return length ? fn( elems[0], key ) : undefined;
+       },
+
+       now: function() {
+               return ( new Date() ).getTime();
+       },
+
+       // Use of jQuery.browser is frowned upon.
+       // More details: http://docs.jquery.com/Utilities/jQuery.browser
+       uaMatch: function( ua ) {
+               ua = ua.toLowerCase();
+
+               var match = rwebkit.exec( ua ) ||
+                       ropera.exec( ua ) ||
+                       rmsie.exec( ua ) ||
+                       ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
+                       [];
+
+               return { browser: match[1] || "", version: match[2] || "0" };
+       },
+
+       sub: function() {
+               function jQuerySub( selector, context ) {
+                       return new jQuerySub.fn.init( selector, context );
+               }
+               jQuery.extend( true, jQuerySub, this );
+               jQuerySub.superclass = this;
+               jQuerySub.fn = jQuerySub.prototype = this();
+               jQuerySub.fn.constructor = jQuerySub;
+               jQuerySub.sub = this.sub;
+               jQuerySub.fn.init = function init( selector, context ) {
+                       if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
+                               context = jQuerySub( context );
+                       }
+
+                       return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
+               };
+               jQuerySub.fn.init.prototype = jQuerySub.fn;
+               var rootjQuerySub = jQuerySub(document);
+               return jQuerySub;
+       },
+
+       browser: {}
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
+       class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+browserMatch = jQuery.uaMatch( userAgent );
+if ( browserMatch.browser ) {
+       jQuery.browser[ browserMatch.browser ] = true;
+       jQuery.browser.version = browserMatch.version;
+}
+
+// Deprecated, use jQuery.browser.webkit instead
+if ( jQuery.browser.webkit ) {
+       jQuery.browser.safari = true;
+}
+
+// IE doesn't match non-breaking spaces with \s
+if ( rnotwhite.test( "\xA0" ) ) {
+       trimLeft = /^[\s\xA0]+/;
+       trimRight = /[\s\xA0]+$/;
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+
+// Cleanup functions for the document ready method
+if ( document.addEventListener ) {
+       DOMContentLoaded = function() {
+               document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
+               jQuery.ready();
+       };
+
+} else if ( document.attachEvent ) {
+       DOMContentLoaded = function() {
+               // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+               if ( document.readyState === "complete" ) {
+                       document.detachEvent( "onreadystatechange", DOMContentLoaded );
+                       jQuery.ready();
+               }
+       };
+}
+
+// The DOM ready check for Internet Explorer
+function doScrollCheck() {
+       if ( jQuery.isReady ) {
+               return;
+       }
+
+       try {
+               // If IE is used, use the trick by Diego Perini
+               // http://javascript.nwbox.com/IEContentLoaded/
+               document.documentElement.doScroll("left");
+       } catch(e) {
+               setTimeout( doScrollCheck, 1 );
+               return;
+       }
+
+       // and execute any waiting functions
+       jQuery.ready();
+}
+
+return jQuery;
+
+})();
+
+
+// String to Object flags format cache
+var flagsCache = {};
+
+// Convert String-formatted flags into Object-formatted ones and store in cache
+function createFlags( flags ) {
+       var object = flagsCache[ flags ] = {},
+               i, length;
+       flags = flags.split( /\s+/ );
+       for ( i = 0, length = flags.length; i < length; i++ ) {
+               object[ flags[i] ] = true;
+       }
+       return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *     flags:  an optional list of space-separated flags that will change how
+ *                     the callback list behaves
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible flags:
+ *
+ *     once:                   will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *     memory:                 will keep track of previous values and will call any callback added
+ *                                     after the list has been fired right away with the latest "memorized"
+ *                                     values (like a Deferred)
+ *
+ *     unique:                 will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *     stopOnFalse:    interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( flags ) {
+
+       // Convert flags from String-formatted to Object-formatted
+       // (we check in cache first)
+       flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
+
+       var // Actual callback list
+               list = [],
+               // Stack of fire calls for repeatable lists
+               stack = [],
+               // Last fire value (for non-forgettable lists)
+               memory,
+               // Flag to know if list is currently firing
+               firing,
+               // First callback to fire (used internally by add and fireWith)
+               firingStart,
+               // End of the loop when firing
+               firingLength,
+               // Index of currently firing callback (modified by remove if needed)
+               firingIndex,
+               // Add one or several callbacks to the list
+               add = function( args ) {
+                       var i,
+                               length,
+                               elem,
+                               type,
+                               actual;
+                       for ( i = 0, length = args.length; i < length; i++ ) {
+                               elem = args[ i ];
+                               type = jQuery.type( elem );
+                               if ( type === "array" ) {
+                                       // Inspect recursively
+                                       add( elem );
+                               } else if ( type === "function" ) {
+                                       // Add if not in unique mode and callback is not in
+                                       if ( !flags.unique || !self.has( elem ) ) {
+                                               list.push( elem );
+                                       }
+                               }
+                       }
+               },
+               // Fire callbacks
+               fire = function( context, args ) {
+                       args = args || [];
+                       memory = !flags.memory || [ context, args ];
+                       firing = true;
+                       firingIndex = firingStart || 0;
+                       firingStart = 0;
+                       firingLength = list.length;
+                       for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+                               if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
+                                       memory = true; // Mark as halted
+                                       break;
+                               }
+                       }
+                       firing = false;
+                       if ( list ) {
+                               if ( !flags.once ) {
+                                       if ( stack && stack.length ) {
+                                               memory = stack.shift();
+                                               self.fireWith( memory[ 0 ], memory[ 1 ] );
+                                       }
+                               } else if ( memory === true ) {
+                                       self.disable();
+                               } else {
+                                       list = [];
+                               }
+                       }
+               },
+               // Actual Callbacks object
+               self = {
+                       // Add a callback or a collection of callbacks to the list
+                       add: function() {
+                               if ( list ) {
+                                       var length = list.length;
+                                       add( arguments );
+                                       // Do we need to add the callbacks to the
+                                       // current firing batch?
+                                       if ( firing ) {
+                                               firingLength = list.length;
+                                       // With memory, if we're not firing then
+                                       // we should call right away, unless previous
+                                       // firing was halted (stopOnFalse)
+                                       } else if ( memory && memory !== true ) {
+                                               firingStart = length;
+                                               fire( memory[ 0 ], memory[ 1 ] );
+                                       }
+                               }
+                               return this;
+                       },
+                       // Remove a callback from the list
+                       remove: function() {
+                               if ( list ) {
+                                       var args = arguments,
+                                               argIndex = 0,
+                                               argLength = args.length;
+                                       for ( ; argIndex < argLength ; argIndex++ ) {
+                                               for ( var i = 0; i < list.length; i++ ) {
+                                                       if ( args[ argIndex ] === list[ i ] ) {
+                                                               // Handle firingIndex and firingLength
+                                                               if ( firing ) {
+                                                                       if ( i <= firingLength ) {
+                                                                               firingLength--;
+                                                                               if ( i <= firingIndex ) {
+                                                                                       firingIndex--;
+                                                                               }
+                                                                       }
+                                                               }
+                                                               // Remove the element
+                                                               list.splice( i--, 1 );
+                                                               // If we have some unicity property then
+                                                               // we only need to do this once
+                                                               if ( flags.unique ) {
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               return this;
+                       },
+                       // Control if a given callback is in the list
+                       has: function( fn ) {
+                               if ( list ) {
+                                       var i = 0,
+                                               length = list.length;
+                                       for ( ; i < length; i++ ) {
+                                               if ( fn === list[ i ] ) {
+                                                       return true;
+                                               }
+                                       }
+                               }
+                               return false;
+                       },
+                       // Remove all callbacks from the list
+                       empty: function() {
+                               list = [];
+                               return this;
+                       },
+                       // Have the list do nothing anymore
+                       disable: function() {
+                               list = stack = memory = undefined;
+                               return this;
+                       },
+                       // Is it disabled?
+                       disabled: function() {
+                               return !list;
+                       },
+                       // Lock the list in its current state
+                       lock: function() {
+                               stack = undefined;
+                               if ( !memory || memory === true ) {
+                                       self.disable();
+                               }
+                               return this;
+                       },
+                       // Is it locked?
+                       locked: function() {
+                               return !stack;
+                       },
+                       // Call all callbacks with the given context and arguments
+                       fireWith: function( context, args ) {
+                               if ( stack ) {
+                                       if ( firing ) {
+                                               if ( !flags.once ) {
+                                                       stack.push( [ context, args ] );
+                                               }
+                                       } else if ( !( flags.once && memory ) ) {
+                                               fire( context, args );
+                                       }
+                               }
+                               return this;
+                       },
+                       // Call all the callbacks with the given arguments
+                       fire: function() {
+                               self.fireWith( this, arguments );
+                               return this;
+                       },
+                       // To know if the callbacks have already been called at least once
+                       fired: function() {
+                               return !!memory;
+                       }
+               };
+
+       return self;
+};
+
+
+
+
+var // Static reference to slice
+       sliceDeferred = [].slice;
+
+jQuery.extend({
+
+       Deferred: function( func ) {
+               var doneList = jQuery.Callbacks( "once memory" ),
+                       failList = jQuery.Callbacks( "once memory" ),
+                       progressList = jQuery.Callbacks( "memory" ),
+                       state = "pending",
+                       lists = {
+                               resolve: doneList,
+                               reject: failList,
+                               notify: progressList
+                       },
+                       promise = {
+                               done: doneList.add,
+                               fail: failList.add,
+                               progress: progressList.add,
+
+                               state: function() {
+                                       return state;
+                               },
+
+                               // Deprecated
+                               isResolved: doneList.fired,
+                               isRejected: failList.fired,
+
+                               then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
+                                       deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
+                                       return this;
+                               },
+                               always: function() {
+                                       deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
+                                       return this;
+                               },
+                               pipe: function( fnDone, fnFail, fnProgress ) {
+                                       return jQuery.Deferred(function( newDefer ) {
+                                               jQuery.each( {
+                                                       done: [ fnDone, "resolve" ],
+                                                       fail: [ fnFail, "reject" ],
+                                                       progress: [ fnProgress, "notify" ]
+                                               }, function( handler, data ) {
+                                                       var fn = data[ 0 ],
+                                                               action = data[ 1 ],
+                                                               returned;
+                                                       if ( jQuery.isFunction( fn ) ) {
+                                                               deferred[ handler ](function() {
+                                                                       returned = fn.apply( this, arguments );
+                                                                       if ( returned && jQuery.isFunction( returned.promise ) ) {
+                                                                               returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
+                                                                       } else {
+                                                                               newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
+                                                                       }
+                                                               });
+                                                       } else {
+                                                               deferred[ handler ]( newDefer[ action ] );
+                                                       }
+                                               });
+                                       }).promise();
+                               },
+                               // Get a promise for this deferred
+                               // If obj is provided, the promise aspect is added to the object
+                               promise: function( obj ) {
+                                       if ( obj == null ) {
+                                               obj = promise;
+                                       } else {
+                                               for ( var key in promise ) {
+                                                       obj[ key ] = promise[ key ];
+                                               }
+                                       }
+                                       return obj;
+                               }
+                       },
+                       deferred = promise.promise({}),
+                       key;
+
+               for ( key in lists ) {
+                       deferred[ key ] = lists[ key ].fire;
+                       deferred[ key + "With" ] = lists[ key ].fireWith;
+               }
+
+               // Handle state
+               deferred.done( function() {
+                       state = "resolved";
+               }, failList.disable, progressList.lock ).fail( function() {
+                       state = "rejected";
+               }, doneList.disable, progressList.lock );
+
+               // Call given func if any
+               if ( func ) {
+                       func.call( deferred, deferred );
+               }
+
+               // All done!
+               return deferred;
+       },
+
+       // Deferred helper
+       when: function( firstParam ) {
+               var args = sliceDeferred.call( arguments, 0 ),
+                       i = 0,
+                       length = args.length,
+                       pValues = new Array( length ),
+                       count = length,
+                       pCount = length,
+                       deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
+                               firstParam :
+                               jQuery.Deferred(),
+                       promise = deferred.promise();
+               function resolveFunc( i ) {
+                       return function( value ) {
+                               args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+                               if ( !( --count ) ) {
+                                       deferred.resolveWith( deferred, args );
+                               }
+                       };
+               }
+               function progressFunc( i ) {
+                       return function( value ) {
+                               pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
+                               deferred.notifyWith( promise, pValues );
+                       };
+               }
+               if ( length > 1 ) {
+                       for ( ; i < length; i++ ) {
+                               if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
+                                       args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
+                               } else {
+                                       --count;
+                               }
+                       }
+                       if ( !count ) {
+                               deferred.resolveWith( deferred, args );
+                       }
+               } else if ( deferred !== firstParam ) {
+                       deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
+               }
+               return promise;
+       }
+});
+
+
+
+
+jQuery.support = (function() {
+
+       var support,
+               all,
+               a,
+               select,
+               opt,
+               input,
+               marginDiv,
+               fragment,
+               tds,
+               events,
+               eventName,
+               i,
+               isSupported,
+               div = document.createElement( "div" ),
+               documentElement = document.documentElement;
+
+       // Preliminary tests
+       div.setAttribute("className", "t");
+       div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+
+       all = div.getElementsByTagName( "*" );
+       a = div.getElementsByTagName( "a" )[ 0 ];
+
+       // Can't get basic test support
+       if ( !all || !all.length || !a ) {
+               return {};
+       }
+
+       // First batch of supports tests
+       select = document.createElement( "select" );
+       opt = select.appendChild( document.createElement("option") );
+       input = div.getElementsByTagName( "input" )[ 0 ];
+
+       support = {
+               // IE strips leading whitespace when .innerHTML is used
+               leadingWhitespace: ( div.firstChild.nodeType === 3 ),
+
+               // Make sure that tbody elements aren't automatically inserted
+               // IE will insert them into empty tables
+               tbody: !div.getElementsByTagName("tbody").length,
+
+               // Make sure that link elements get serialized correctly by innerHTML
+               // This requires a wrapper element in IE
+               htmlSerialize: !!div.getElementsByTagName("link").length,
+
+               // Get the style information from getAttribute
+               // (IE uses .cssText instead)
+               style: /top/.test( a.getAttribute("style") ),
+
+               // Make sure that URLs aren't manipulated
+               // (IE normalizes it by default)
+               hrefNormalized: ( a.getAttribute("href") === "/a" ),
+
+               // Make sure that element opacity exists
+               // (IE uses filter instead)
+               // Use a regex to work around a WebKit issue. See #5145
+               opacity: /^0.55/.test( a.style.opacity ),
+
+               // Verify style float existence
+               // (IE uses styleFloat instead of cssFloat)
+               cssFloat: !!a.style.cssFloat,
+
+               // Make sure that if no value is specified for a checkbox
+               // that it defaults to "on".
+               // (WebKit defaults to "" instead)
+               checkOn: ( input.value === "on" ),
+
+               // Make sure that a selected-by-default option has a working selected property.
+               // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+               optSelected: opt.selected,
+
+               // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+               getSetAttribute: div.className !== "t",
+
+               // Tests for enctype support on a form(#6743)
+               enctype: !!document.createElement("form").enctype,
+
+               // Makes sure cloning an html5 element does not cause problems
+               // Where outerHTML is undefined, this still works
+               html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
+
+               // Will be defined later
+               submitBubbles: true,
+               changeBubbles: true,
+               focusinBubbles: false,
+               deleteExpando: true,
+               noCloneEvent: true,
+               inlineBlockNeedsLayout: false,
+               shrinkWrapBlocks: false,
+               reliableMarginRight: true
+       };
+
+       // Make sure checked status is properly cloned
+       input.checked = true;
+       support.noCloneChecked = input.cloneNode( true ).checked;
+
+       // Make sure that the options inside disabled selects aren't marked as disabled
+       // (WebKit marks them as disabled)
+       select.disabled = true;
+       support.optDisabled = !opt.disabled;
+
+       // Test to see if it's possible to delete an expando from an element
+       // Fails in Internet Explorer
+       try {
+               delete div.test;
+       } catch( e ) {
+               support.deleteExpando = false;
+       }
+
+       if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
+               div.attachEvent( "onclick", function() {
+                       // Cloning a node shouldn't copy over any
+                       // bound event handlers (IE does this)
+                       support.noCloneEvent = false;
+               });
+               div.cloneNode( true ).fireEvent( "onclick" );
+       }
+
+       // Check if a radio maintains its value
+       // after being appended to the DOM
+       input = document.createElement("input");
+       input.value = "t";
+       input.setAttribute("type", "radio");
+       support.radioValue = input.value === "t";
+
+       input.setAttribute("checked", "checked");
+       div.appendChild( input );
+       fragment = document.createDocumentFragment();
+       fragment.appendChild( div.lastChild );
+
+       // WebKit doesn't clone checked state correctly in fragments
+       support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+       // Check if a disconnected checkbox will retain its checked
+       // value of true after appended to the DOM (IE6/7)
+       support.appendChecked = input.checked;
+
+       fragment.removeChild( input );
+       fragment.appendChild( div );
+
+       div.innerHTML = "";
+
+       // Check if div with explicit width and no margin-right incorrectly
+       // gets computed margin-right based on width of container. For more
+       // info see bug #3333
+       // Fails in WebKit before Feb 2011 nightlies
+       // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+       if ( window.getComputedStyle ) {
+               marginDiv = document.createElement( "div" );
+               marginDiv.style.width = "0";
+               marginDiv.style.marginRight = "0";
+               div.style.width = "2px";
+               div.appendChild( marginDiv );
+               support.reliableMarginRight =
+                       ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
+       }
+
+       // Technique from Juriy Zaytsev
+       // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+       // We only care about the case where non-standard event systems
+       // are used, namely in IE. Short-circuiting here helps us to
+       // avoid an eval call (in setAttribute) which can cause CSP
+       // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
+       if ( div.attachEvent ) {
+               for( i in {
+                       submit: 1,
+                       change: 1,
+                       focusin: 1
+               }) {
+                       eventName = "on" + i;
+                       isSupported = ( eventName in div );
+                       if ( !isSupported ) {
+                               div.setAttribute( eventName, "return;" );
+                               isSupported = ( typeof div[ eventName ] === "function" );
+                       }
+                       support[ i + "Bubbles" ] = isSupported;
+               }
+       }
+
+       fragment.removeChild( div );
+
+       // Null elements to avoid leaks in IE
+       fragment = select = opt = marginDiv = div = input = null;
+
+       // Run tests that need a body at doc ready
+       jQuery(function() {
+               var container, outer, inner, table, td, offsetSupport,
+                       conMarginTop, ptlm, vb, style, html,
+                       body = document.getElementsByTagName("body")[0];
+
+               if ( !body ) {
+                       // Return for frameset docs that don't have a body
+                       return;
+               }
+
+               conMarginTop = 1;
+               ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
+               vb = "visibility:hidden;border:0;";
+               style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
+               html = "<div " + style + "><div></div></div>" +
+                       "<table " + style + " cellpadding='0' cellspacing='0'>" +
+                       "<tr><td></td></tr></table>";
+
+               container = document.createElement("div");
+               container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
+               body.insertBefore( container, body.firstChild );
+
+               // Construct the test element
+               div = document.createElement("div");
+               container.appendChild( div );
+
+               // Check if table cells still have offsetWidth/Height when they are set
+               // to display:none and there are still other visible table cells in a
+               // table row; if so, offsetWidth/Height are not reliable for use when
+               // determining if an element has been hidden directly using
+               // display:none (it is still safe to use offsets if a parent element is
+               // hidden; don safety goggles and see bug #4512 for more information).
+               // (only IE 8 fails this test)
+               div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
+               tds = div.getElementsByTagName( "td" );
+               isSupported = ( tds[ 0 ].offsetHeight === 0 );
+
+               tds[ 0 ].style.display = "";
+               tds[ 1 ].style.display = "none";
+
+               // Check if empty table cells still have offsetWidth/Height
+               // (IE <= 8 fail this test)
+               support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
+
+               // Figure out if the W3C box model works as expected
+               div.innerHTML = "";
+               div.style.width = div.style.paddingLeft = "1px";
+               jQuery.boxModel = support.boxModel = div.offsetWidth === 2;
+
+               if ( typeof div.style.zoom !== "undefined" ) {
+                       // Check if natively block-level elements act like inline-block
+                       // elements when setting their display to 'inline' and giving
+                       // them layout
+                       // (IE < 8 does this)
+                       div.style.display = "inline";
+                       div.style.zoom = 1;
+                       support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
+
+                       // Check if elements with layout shrink-wrap their children
+                       // (IE 6 does this)
+                       div.style.display = "";
+                       div.innerHTML = "<div style='width:4px;'></div>";
+                       support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
+               }
+
+               div.style.cssText = ptlm + vb;
+               div.innerHTML = html;
+
+               outer = div.firstChild;
+               inner = outer.firstChild;
+               td = outer.nextSibling.firstChild.firstChild;
+
+               offsetSupport = {
+                       doesNotAddBorder: ( inner.offsetTop !== 5 ),
+                       doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
+               };
+
+               inner.style.position = "fixed";
+               inner.style.top = "20px";
+
+               // safari subtracts parent border width here which is 5px
+               offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
+               inner.style.position = inner.style.top = "";
+
+               outer.style.overflow = "hidden";
+               outer.style.position = "relative";
+
+               offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
+               offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );
+
+               body.removeChild( container );
+               div  = container = null;
+
+               jQuery.extend( support, offsetSupport );
+       });
+
+       return support;
+})();
+
+
+
+
+var rbrace = /^(?:\{.*\}|\[.*\])$/,
+       rmultiDash = /([A-Z])/g;
+
+jQuery.extend({
+       cache: {},
+
+       // Please use with caution
+       uuid: 0,
+
+       // Unique for each copy of jQuery on the page
+       // Non-digits removed to match rinlinejQuery
+       expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
+
+       // The following elements throw uncatchable exceptions if you
+       // attempt to add expando properties to them.
+       noData: {
+               "embed": true,
+               // Ban all objects except for Flash (which handle expandos)
+               "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
+               "applet": true
+       },
+
+       hasData: function( elem ) {
+               elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+               return !!elem && !isEmptyDataObject( elem );
+       },
+
+       data: function( elem, name, data, pvt /* Internal Use Only */ ) {
+               if ( !jQuery.acceptData( elem ) ) {
+                       return;
+               }
+
+               var privateCache, thisCache, ret,
+                       internalKey = jQuery.expando,
+                       getByName = typeof name === "string",
+
+                       // We have to handle DOM nodes and JS objects differently because IE6-7
+                       // can't GC object references properly across the DOM-JS boundary
+                       isNode = elem.nodeType,
+
+                       // Only DOM nodes need the global jQuery cache; JS object data is
+                       // attached directly to the object so GC can occur automatically
+                       cache = isNode ? jQuery.cache : elem,
+
+                       // Only defining an ID for JS objects if its cache already exists allows
+                       // the code to shortcut on the same path as a DOM node with no cache
+                       id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey,
+                       isEvents = name === "events";
+
+               // Avoid doing any more work than we need to when trying to get data on an
+               // object that has no data at all
+               if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) {
+                       return;
+               }
+
+               if ( !id ) {
+                       // Only DOM nodes need a new unique ID for each element since their data
+                       // ends up in the global cache
+                       if ( isNode ) {
+                               elem[ internalKey ] = id = ++jQuery.uuid;
+                       } else {
+                               id = internalKey;
+                       }
+               }
+
+               if ( !cache[ id ] ) {
+                       cache[ id ] = {};
+
+                       // Avoids exposing jQuery metadata on plain JS objects when the object
+                       // is serialized using JSON.stringify
+                       if ( !isNode ) {
+                               cache[ id ].toJSON = jQuery.noop;
+                       }
+               }
+
+               // An object can be passed to jQuery.data instead of a key/value pair; this gets
+               // shallow copied over onto the existing cache
+               if ( typeof name === "object" || typeof name === "function" ) {
+                       if ( pvt ) {
+                               cache[ id ] = jQuery.extend( cache[ id ], name );
+                       } else {
+                               cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+                       }
+               }
+
+               privateCache = thisCache = cache[ id ];
+
+               // jQuery data() is stored in a separate object inside the object's internal data
+               // cache in order to avoid key collisions between internal data and user-defined
+               // data.
+               if ( !pvt ) {
+                       if ( !thisCache.data ) {
+                               thisCache.data = {};
+                       }
+
+                       thisCache = thisCache.data;
+               }
+
+               if ( data !== undefined ) {
+                       thisCache[ jQuery.camelCase( name ) ] = data;
+               }
+
+               // Users should not attempt to inspect the internal events object using jQuery.data,
+               // it is undocumented and subject to change. But does anyone listen? No.
+               if ( isEvents && !thisCache[ name ] ) {
+                       return privateCache.events;
+               }
+
+               // Check for both converted-to-camel and non-converted data property names
+               // If a data property was specified
+               if ( getByName ) {
+
+                       // First Try to find as-is property data
+                       ret = thisCache[ name ];
+
+                       // Test for null|undefined property data
+                       if ( ret == null ) {
+
+                               // Try to find the camelCased property
+                               ret = thisCache[ jQuery.camelCase( name ) ];
+                       }
+               } else {
+                       ret = thisCache;
+               }
+
+               return ret;
+       },
+
+       removeData: function( elem, name, pvt /* Internal Use Only */ ) {
+               if ( !jQuery.acceptData( elem ) ) {
+                       return;
+               }
+
+               var thisCache, i, l,
+
+                       // Reference to internal data cache key
+                       internalKey = jQuery.expando,
+
+                       isNode = elem.nodeType,
+
+                       // See jQuery.data for more information
+                       cache = isNode ? jQuery.cache : elem,
+
+                       // See jQuery.data for more information
+                       id = isNode ? elem[ internalKey ] : internalKey;
+
+               // If there is already no cache entry for this object, there is no
+               // purpose in continuing
+               if ( !cache[ id ] ) {
+                       return;
+               }
+
+               if ( name ) {
+
+                       thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+                       if ( thisCache ) {
+
+                               // Support array or space separated string names for data keys
+                               if ( !jQuery.isArray( name ) ) {
+
+                                       // try the string as a key before any manipulation
+                                       if ( name in thisCache ) {
+                                               name = [ name ];
+                                       } else {
+
+                                               // split the camel cased version by spaces unless a key with the spaces exists
+                                               name = jQuery.camelCase( name );
+                                               if ( name in thisCache ) {
+                                                       name = [ name ];
+                                               } else {
+                                                       name = name.split( " " );
+                                               }
+                                       }
+                               }
+
+                               for ( i = 0, l = name.length; i < l; i++ ) {
+                                       delete thisCache[ name[i] ];
+                               }
+
+                               // If there is no data left in the cache, we want to continue
+                               // and let the cache object itself get destroyed
+                               if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
+                                       return;
+                               }
+                       }
+               }
+
+               // See jQuery.data for more information
+               if ( !pvt ) {
+                       delete cache[ id ].data;
+
+                       // Don't destroy the parent cache unless the internal data object
+                       // had been the only thing left in it
+                       if ( !isEmptyDataObject(cache[ id ]) ) {
+                               return;
+                       }
+               }
+
+               // Browsers that fail expando deletion also refuse to delete expandos on
+               // the window, but it will allow it on all other JS objects; other browsers
+               // don't care
+               // Ensure that `cache` is not a window object #10080
+               if ( jQuery.support.deleteExpando || !cache.setInterval ) {
+                       delete cache[ id ];
+               } else {
+                       cache[ id ] = null;
+               }
+
+               // We destroyed the cache and need to eliminate the expando on the node to avoid
+               // false lookups in the cache for entries that no longer exist
+               if ( isNode ) {
+                       // IE does not allow us to delete expando properties from nodes,
+                       // nor does it have a removeAttribute function on Document nodes;
+                       // we must handle all of these cases
+                       if ( jQuery.support.deleteExpando ) {
+                               delete elem[ internalKey ];
+                       } else if ( elem.removeAttribute ) {
+                               elem.removeAttribute( internalKey );
+                       } else {
+                               elem[ internalKey ] = null;
+                       }
+               }
+       },
+
+       // For internal use only.
+       _data: function( elem, name, data ) {
+               return jQuery.data( elem, name, data, true );
+       },
+
+       // A method for determining if a DOM node can handle the data expando
+       acceptData: function( elem ) {
+               if ( elem.nodeName ) {
+                       var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
+
+                       if ( match ) {
+                               return !(match === true || elem.getAttribute("classid") !== match);
+                       }
+               }
+
+               return true;
+       }
+});
+
+jQuery.fn.extend({
+       data: function( key, value ) {
+               var parts, attr, name,
+                       data = null;
+
+               if ( typeof key === "undefined" ) {
+                       if ( this.length ) {
+                               data = jQuery.data( this[0] );
+
+                               if ( this[0].nodeType === 1 && !jQuery._data( this[0], "parsedAttrs" ) ) {
+                                       attr = this[0].attributes;
+                                       for ( var i = 0, l = attr.length; i < l; i++ ) {
+                                               name = attr[i].name;
+
+                                               if ( name.indexOf( "data-" ) === 0 ) {
+                                                       name = jQuery.camelCase( name.substring(5) );
+
+                                                       dataAttr( this[0], name, data[ name ] );
+                                               }
+                                       }
+                                       jQuery._data( this[0], "parsedAttrs", true );
+                               }
+                       }
+
+                       return data;
+
+               } else if ( typeof key === "object" ) {
+                       return this.each(function() {
+                               jQuery.data( this, key );
+                       });
+               }
+
+               parts = key.split(".");
+               parts[1] = parts[1] ? "." + parts[1] : "";
+
+               if ( value === undefined ) {
+                       data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
+
+                       // Try to fetch any internally stored data first
+                       if ( data === undefined && this.length ) {
+                               data = jQuery.data( this[0], key );
+                               data = dataAttr( this[0], key, data );
+                       }
+
+                       return data === undefined && parts[1] ?
+                               this.data( parts[0] ) :
+                               data;
+
+               } else {
+                       return this.each(function() {
+                               var self = jQuery( this ),
+                                       args = [ parts[0], value ];
+
+                               self.triggerHandler( "setData" + parts[1] + "!", args );
+                               jQuery.data( this, key, value );
+                               self.triggerHandler( "changeData" + parts[1] + "!", args );
+                       });
+               }
+       },
+
+       removeData: function( key ) {
+               return this.each(function() {
+                       jQuery.removeData( this, key );
+               });
+       }
+});
+
+function dataAttr( elem, key, data ) {
+       // If nothing was found internally, try to fetch any
+       // data from the HTML5 data-* attribute
+       if ( data === undefined && elem.nodeType === 1 ) {
+
+               var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+               data = elem.getAttribute( name );
+
+               if ( typeof data === "string" ) {
+                       try {
+                               data = data === "true" ? true :
+                               data === "false" ? false :
+                               data === "null" ? null :
+                               jQuery.isNumeric( data ) ? parseFloat( data ) :
+                                       rbrace.test( data ) ? jQuery.parseJSON( data ) :
+                                       data;
+                       } catch( e ) {}
+
+                       // Make sure we set the data so it isn't changed later
+                       jQuery.data( elem, key, data );
+
+               } else {
+                       data = undefined;
+               }
+       }
+
+       return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+       for ( var name in obj ) {
+
+               // if the public data object is empty, the private is still empty
+               if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+                       continue;
+               }
+               if ( name !== "toJSON" ) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+
+
+
+function handleQueueMarkDefer( elem, type, src ) {
+       var deferDataKey = type + "defer",
+               queueDataKey = type + "queue",
+               markDataKey = type + "mark",
+               defer = jQuery._data( elem, deferDataKey );
+       if ( defer &&
+               ( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
+               ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
+               // Give room for hard-coded callbacks to fire first
+               // and eventually mark/queue something else on the element
+               setTimeout( function() {
+                       if ( !jQuery._data( elem, queueDataKey ) &&
+                               !jQuery._data( elem, markDataKey ) ) {
+                               jQuery.removeData( elem, deferDataKey, true );
+                               defer.fire();
+                       }
+               }, 0 );
+       }
+}
+
+jQuery.extend({
+
+       _mark: function( elem, type ) {
+               if ( elem ) {
+                       type = ( type || "fx" ) + "mark";
+                       jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
+               }
+       },
+
+       _unmark: function( force, elem, type ) {
+               if ( force !== true ) {
+                       type = elem;
+                       elem = force;
+                       force = false;
+               }
+               if ( elem ) {
+                       type = type || "fx";
+                       var key = type + "mark",
+                               count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
+                       if ( count ) {
+                               jQuery._data( elem, key, count );
+                       } else {
+                               jQuery.removeData( elem, key, true );
+                               handleQueueMarkDefer( elem, type, "mark" );
+                       }
+               }
+       },
+
+       queue: function( elem, type, data ) {
+               var q;
+               if ( elem ) {
+                       type = ( type || "fx" ) + "queue";
+                       q = jQuery._data( elem, type );
+
+                       // Speed up dequeue by getting out quickly if this is just a lookup
+                       if ( data ) {
+                               if ( !q || jQuery.isArray(data) ) {
+                                       q = jQuery._data( elem, type, jQuery.makeArray(data) );
+                               } else {
+                                       q.push( data );
+                               }
+                       }
+                       return q || [];
+               }
+       },
+
+       dequeue: function( elem, type ) {
+               type = type || "fx";
+
+               var queue = jQuery.queue( elem, type ),
+                       fn = queue.shift(),
+                       hooks = {};
+
+               // If the fx queue is dequeued, always remove the progress sentinel
+               if ( fn === "inprogress" ) {
+                       fn = queue.shift();
+               }
+
+               if ( fn ) {
+                       // Add a progress sentinel to prevent the fx queue from being
+                       // automatically dequeued
+                       if ( type === "fx" ) {
+                               queue.unshift( "inprogress" );
+                       }
+
+                       jQuery._data( elem, type + ".run", hooks );
+                       fn.call( elem, function() {
+                               jQuery.dequeue( elem, type );
+                       }, hooks );
+               }
+
+               if ( !queue.length ) {
+                       jQuery.removeData( elem, type + "queue " + type + ".run", true );
+                       handleQueueMarkDefer( elem, type, "queue" );
+               }
+       }
+});
+
+jQuery.fn.extend({
+       queue: function( type, data ) {
+               if ( typeof type !== "string" ) {
+                       data = type;
+                       type = "fx";
+               }
+
+               if ( data === undefined ) {
+                       return jQuery.queue( this[0], type );
+               }
+               return this.each(function() {
+                       var queue = jQuery.queue( this, type, data );
+
+                       if ( type === "fx" && queue[0] !== "inprogress" ) {
+                               jQuery.dequeue( this, type );
+                       }
+               });
+       },
+       dequeue: function( type ) {
+               return this.each(function() {
+                       jQuery.dequeue( this, type );
+               });
+       },
+       // Based off of the plugin by Clint Helfers, with permission.
+       // http://blindsignals.com/index.php/2009/07/jquery-delay/
+       delay: function( time, type ) {
+               time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+               type = type || "fx";
+
+               return this.queue( type, function( next, hooks ) {
+                       var timeout = setTimeout( next, time );
+                       hooks.stop = function() {
+                               clearTimeout( timeout );
+                       };
+               });
+       },
+       clearQueue: function( type ) {
+               return this.queue( type || "fx", [] );
+       },
+       // Get a promise resolved when queues of a certain type
+       // are emptied (fx is the type by default)
+       promise: function( type, object ) {
+               if ( typeof type !== "string" ) {
+                       object = type;
+                       type = undefined;
+               }
+               type = type || "fx";
+               var defer = jQuery.Deferred(),
+                       elements = this,
+                       i = elements.length,
+                       count = 1,
+                       deferDataKey = type + "defer",
+                       queueDataKey = type + "queue",
+                       markDataKey = type + "mark",
+                       tmp;
+               function resolve() {
+                       if ( !( --count ) ) {
+                               defer.resolveWith( elements, [ elements ] );
+                       }
+               }
+               while( i-- ) {
+                       if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
+                                       ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
+                                               jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
+                                       jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
+                               count++;
+                               tmp.add( resolve );
+                       }
+               }
+               resolve();
+               return defer.promise();
+       }
+});
+
+
+
+
+var rclass = /[\n\t\r]/g,
+       rspace = /\s+/,
+       rreturn = /\r/g,
+       rtype = /^(?:button|input)$/i,
+       rfocusable = /^(?:button|input|object|select|textarea)$/i,
+       rclickable = /^a(?:rea)?$/i,
+       rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
+       getSetAttribute = jQuery.support.getSetAttribute,
+       nodeHook, boolHook, fixSpecified;
+
+jQuery.fn.extend({
+       attr: function( name, value ) {
+               return jQuery.access( this, name, value, true, jQuery.attr );
+       },
+
+       removeAttr: function( name ) {
+               return this.each(function() {
+                       jQuery.removeAttr( this, name );
+               });
+       },
+
+       prop: function( name, value ) {
+               return jQuery.access( this, name, value, true, jQuery.prop );
+       },
+
+       removeProp: function( name ) {
+               name = jQuery.propFix[ name ] || name;
+               return this.each(function() {
+                       // try/catch handles cases where IE balks (such as removing a property on window)
+                       try {
+                               this[ name ] = undefined;
+                               delete this[ name ];
+                       } catch( e ) {}
+               });
+       },
+
+       addClass: function( value ) {
+               var classNames, i, l, elem,
+                       setClass, c, cl;
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( j ) {
+                               jQuery( this ).addClass( value.call(this, j, this.className) );
+                       });
+               }
+
+               if ( value && typeof value === "string" ) {
+                       classNames = value.split( rspace );
+
+                       for ( i = 0, l = this.length; i < l; i++ ) {
+                               elem = this[ i ];
+
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !elem.className && classNames.length === 1 ) {
+                                               elem.className = value;
+
+                                       } else {
+                                               setClass = " " + elem.className + " ";
+
+                                               for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+                                                       if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) {
+                                                               setClass += classNames[ c ] + " ";
+                                                       }
+                                               }
+                                               elem.className = jQuery.trim( setClass );
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       removeClass: function( value ) {
+               var classNames, i, l, elem, className, c, cl;
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( j ) {
+                               jQuery( this ).removeClass( value.call(this, j, this.className) );
+                       });
+               }
+
+               if ( (value && typeof value === "string") || value === undefined ) {
+                       classNames = ( value || "" ).split( rspace );
+
+                       for ( i = 0, l = this.length; i < l; i++ ) {
+                               elem = this[ i ];
+
+                               if ( elem.nodeType === 1 && elem.className ) {
+                                       if ( value ) {
+                                               className = (" " + elem.className + " ").replace( rclass, " " );
+                                               for ( c = 0, cl = classNames.length; c < cl; c++ ) {
+                                                       className = className.replace(" " + classNames[ c ] + " ", " ");
+                                               }
+                                               elem.className = jQuery.trim( className );
+
+                                       } else {
+                                               elem.className = "";
+                                       }
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       toggleClass: function( value, stateVal ) {
+               var type = typeof value,
+                       isBool = typeof stateVal === "boolean";
+
+               if ( jQuery.isFunction( value ) ) {
+                       return this.each(function( i ) {
+                               jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+                       });
+               }
+
+               return this.each(function() {
+                       if ( type === "string" ) {
+                               // toggle individual class names
+                               var className,
+                                       i = 0,
+                                       self = jQuery( this ),
+                                       state = stateVal,
+                                       classNames = value.split( rspace );
+
+                               while ( (className = classNames[ i++ ]) ) {
+                                       // check each className given, space seperated list
+                                       state = isBool ? state : !self.hasClass( className );
+                                       self[ state ? "addClass" : "removeClass" ]( className );
+                               }
+
+                       } else if ( type === "undefined" || type === "boolean" ) {
+                               if ( this.className ) {
+                                       // store className if set
+                                       jQuery._data( this, "__className__", this.className );
+                               }
+
+                               // toggle whole className
+                               this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+                       }
+               });
+       },
+
+       hasClass: function( selector ) {
+               var className = " " + selector + " ",
+                       i = 0,
+                       l = this.length;
+               for ( ; i < l; i++ ) {
+                       if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
+                               return true;
+                       }
+               }
+
+               return false;
+       },
+
+       val: function( value ) {
+               var hooks, ret, isFunction,
+                       elem = this[0];
+
+               if ( !arguments.length ) {
+                       if ( elem ) {
+                               hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
+
+                               if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+                                       return ret;
+                               }
+
+                               ret = elem.value;
+
+                               return typeof ret === "string" ?
+                                       // handle most common string cases
+                                       ret.replace(rreturn, "") :
+                                       // handle cases where value is null/undef or number
+                                       ret == null ? "" : ret;
+                       }
+
+                       return;
+               }
+
+               isFunction = jQuery.isFunction( value );
+
+               return this.each(function( i ) {
+                       var self = jQuery(this), val;
+
+                       if ( this.nodeType !== 1 ) {
+                               return;
+                       }
+
+                       if ( isFunction ) {
+                               val = value.call( this, i, self.val() );
+                       } else {
+                               val = value;
+                       }
+
+                       // Treat null/undefined as ""; convert numbers to string
+                       if ( val == null ) {
+                               val = "";
+                       } else if ( typeof val === "number" ) {
+                               val += "";
+                       } else if ( jQuery.isArray( val ) ) {
+                               val = jQuery.map(val, function ( value ) {
+                                       return value == null ? "" : value + "";
+                               });
+                       }
+
+                       hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
+
+                       // If set returns undefined, fall back to normal setting
+                       if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+                               this.value = val;
+                       }
+               });
+       }
+});
+
+jQuery.extend({
+       valHooks: {
+               option: {
+                       get: function( elem ) {
+                               // attributes.value is undefined in Blackberry 4.7 but
+                               // uses .value. See #6932
+                               var val = elem.attributes.value;
+                               return !val || val.specified ? elem.value : elem.text;
+                       }
+               },
+               select: {
+                       get: function( elem ) {
+                               var value, i, max, option,
+                                       index = elem.selectedIndex,
+                                       values = [],
+                                       options = elem.options,
+                                       one = elem.type === "select-one";
+
+                               // Nothing was selected
+                               if ( index < 0 ) {
+                                       return null;
+                               }
+
+                               // Loop through all the selected options
+                               i = one ? index : 0;
+                               max = one ? index + 1 : options.length;
+                               for ( ; i < max; i++ ) {
+                                       option = options[ i ];
+
+                                       // Don't return options that are disabled or in a disabled optgroup
+                                       if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
+                                                       (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
+
+                                               // Get the specific value for the option
+                                               value = jQuery( option ).val();
+
+                                               // We don't need an array for one selects
+                                               if ( one ) {
+                                                       return value;
+                                               }
+
+                                               // Multi-Selects return an array
+                                               values.push( value );
+                                       }
+                               }
+
+                               // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
+                               if ( one && !values.length && options.length ) {
+                                       return jQuery( options[ index ] ).val();
+                               }
+
+                               return values;
+                       },
+
+                       set: function( elem, value ) {
+                               var values = jQuery.makeArray( value );
+
+                               jQuery(elem).find("option").each(function() {
+                                       this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
+                               });
+
+                               if ( !values.length ) {
+                                       elem.selectedIndex = -1;
+                               }
+                               return values;
+                       }
+               }
+       },
+
+       attrFn: {
+               val: true,
+               css: true,
+               html: true,
+               text: true,
+               data: true,
+               width: true,
+               height: true,
+               offset: true
+       },
+
+       attr: function( elem, name, value, pass ) {
+               var ret, hooks, notxml,
+                       nType = elem.nodeType;
+
+               // don't get/set attributes on text, comment and attribute nodes
+               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+                       return;
+               }
+
+               if ( pass && name in jQuery.attrFn ) {
+                       return jQuery( elem )[ name ]( value );
+               }
+
+               // Fallback to prop when attributes are not supported
+               if ( typeof elem.getAttribute === "undefined" ) {
+                       return jQuery.prop( elem, name, value );
+               }
+
+               notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+               // All attributes are lowercase
+               // Grab necessary hook if one is defined
+               if ( notxml ) {
+                       name = name.toLowerCase();
+                       hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
+               }
+
+               if ( value !== undefined ) {
+
+                       if ( value === null ) {
+                               jQuery.removeAttr( elem, name );
+                               return;
+
+                       } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
+                               return ret;
+
+                       } else {
+                               elem.setAttribute( name, "" + value );
+                               return value;
+                       }
+
+               } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
+                       return ret;
+
+               } else {
+
+                       ret = elem.getAttribute( name );
+
+                       // Non-existent attributes return null, we normalize to undefined
+                       return ret === null ?
+                               undefined :
+                               ret;
+               }
+       },
+
+       removeAttr: function( elem, value ) {
+               var propName, attrNames, name, l,
+                       i = 0;
+
+               if ( value && elem.nodeType === 1 ) {
+                       attrNames = value.toLowerCase().split( rspace );
+                       l = attrNames.length;
+
+                       for ( ; i < l; i++ ) {
+                               name = attrNames[ i ];
+
+                               if ( name ) {
+                                       propName = jQuery.propFix[ name ] || name;
+
+                                       // See #9699 for explanation of this approach (setting first, then removal)
+                                       jQuery.attr( elem, name, "" );
+                                       elem.removeAttribute( getSetAttribute ? name : propName );
+
+                                       // Set corresponding property to false for boolean attributes
+                                       if ( rboolean.test( name ) && propName in elem ) {
+                                               elem[ propName ] = false;
+                                       }
+                               }
+                       }
+               }
+       },
+
+       attrHooks: {
+               type: {
+                       set: function( elem, value ) {
+                               // We can't allow the type property to be changed (since it causes problems in IE)
+                               if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
+                                       jQuery.error( "type property can't be changed" );
+                               } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+                                       // Setting the type on a radio button after the value resets the value in IE6-9
+                                       // Reset value to it's default in case type is set after value
+                                       // This is for element creation
+                                       var val = elem.value;
+                                       elem.setAttribute( "type", value );
+                                       if ( val ) {
+                                               elem.value = val;
+                                       }
+                                       return value;
+                               }
+                       }
+               },
+               // Use the value property for back compat
+               // Use the nodeHook for button elements in IE6/7 (#1954)
+               value: {
+                       get: function( elem, name ) {
+                               if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+                                       return nodeHook.get( elem, name );
+                               }
+                               return name in elem ?
+                                       elem.value :
+                                       null;
+                       },
+                       set: function( elem, value, name ) {
+                               if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
+                                       return nodeHook.set( elem, value, name );
+                               }
+                               // Does not return so that setAttribute is also used
+                               elem.value = value;
+                       }
+               }
+       },
+
+       propFix: {
+               tabindex: "tabIndex",
+               readonly: "readOnly",
+               "for": "htmlFor",
+               "class": "className",
+               maxlength: "maxLength",
+               cellspacing: "cellSpacing",
+               cellpadding: "cellPadding",
+               rowspan: "rowSpan",
+               colspan: "colSpan",
+               usemap: "useMap",
+               frameborder: "frameBorder",
+               contenteditable: "contentEditable"
+       },
+
+       prop: function( elem, name, value ) {
+               var ret, hooks, notxml,
+                       nType = elem.nodeType;
+
+               // don't get/set properties on text, comment and attribute nodes
+               if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+                       return;
+               }
+
+               notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+               if ( notxml ) {
+                       // Fix name and attach hooks
+                       name = jQuery.propFix[ name ] || name;
+                       hooks = jQuery.propHooks[ name ];
+               }
+
+               if ( value !== undefined ) {
+                       if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+                               return ret;
+
+                       } else {
+                               return ( elem[ name ] = value );
+                       }
+
+               } else {
+                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+                               return ret;
+
+                       } else {
+                               return elem[ name ];
+                       }
+               }
+       },
+
+       propHooks: {
+               tabIndex: {
+                       get: function( elem ) {
+                               // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+                               // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+                               var attributeNode = elem.getAttributeNode("tabindex");
+
+                               return attributeNode && attributeNode.specified ?
+                                       parseInt( attributeNode.value, 10 ) :
+                                       rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+                                               0 :
+                                               undefined;
+                       }
+               }
+       }
+});
+
+// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
+jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
+
+// Hook for boolean attributes
+boolHook = {
+       get: function( elem, name ) {
+               // Align boolean attributes with corresponding properties
+               // Fall back to attribute presence where some booleans are not supported
+               var attrNode,
+                       property = jQuery.prop( elem, name );
+               return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
+                       name.toLowerCase() :
+                       undefined;
+       },
+       set: function( elem, value, name ) {
+               var propName;
+               if ( value === false ) {
+                       // Remove boolean attributes when set to false
+                       jQuery.removeAttr( elem, name );
+               } else {
+                       // value is true since we know at this point it's type boolean and not false
+                       // Set boolean attributes to the same name and set the DOM property
+                       propName = jQuery.propFix[ name ] || name;
+                       if ( propName in elem ) {
+                               // Only set the IDL specifically if it already exists on the element
+                               elem[ propName ] = true;
+                       }
+
+                       elem.setAttribute( name, name.toLowerCase() );
+               }
+               return name;
+       }
+};
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+       fixSpecified = {
+               name: true,
+               id: true
+       };
+
+       // Use this for any attribute in IE6/7
+       // This fixes almost every IE6/7 issue
+       nodeHook = jQuery.valHooks.button = {
+               get: function( elem, name ) {
+                       var ret;
+                       ret = elem.getAttributeNode( name );
+                       return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
+                               ret.nodeValue :
+                               undefined;
+               },
+               set: function( elem, value, name ) {
+                       // Set the existing or create a new attribute node
+                       var ret = elem.getAttributeNode( name );
+                       if ( !ret ) {
+                               ret = document.createAttribute( name );
+                               elem.setAttributeNode( ret );
+                       }
+                       return ( ret.nodeValue = value + "" );
+               }
+       };
+
+       // Apply the nodeHook to tabindex
+       jQuery.attrHooks.tabindex.set = nodeHook.set;
+
+       // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+       // This is for removals
+       jQuery.each([ "width", "height" ], function( i, name ) {
+               jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+                       set: function( elem, value ) {
+                               if ( value === "" ) {
+                                       elem.setAttribute( name, "auto" );
+                                       return value;
+                               }
+                       }
+               });
+       });
+
+       // Set contenteditable to false on removals(#10429)
+       // Setting to empty string throws an error as an invalid value
+       jQuery.attrHooks.contenteditable = {
+               get: nodeHook.get,
+               set: function( elem, value, name ) {
+                       if ( value === "" ) {
+                               value = "false";
+                       }
+                       nodeHook.set( elem, value, name );
+               }
+       };
+}
+
+
+// Some attributes require a special call on IE
+if ( !jQuery.support.hrefNormalized ) {
+       jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
+               jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
+                       get: function( elem ) {
+                               var ret = elem.getAttribute( name, 2 );
+                               return ret === null ? undefined : ret;
+                       }
+               });
+       });
+}
+
+if ( !jQuery.support.style ) {
+       jQuery.attrHooks.style = {
+               get: function( elem ) {
+                       // Return undefined in the case of empty string
+                       // Normalize to lowercase since IE uppercases css property names
+                       return elem.style.cssText.toLowerCase() || undefined;
+               },
+               set: function( elem, value ) {
+                       return ( elem.style.cssText = "" + value );
+               }
+       };
+}
+
+// Safari mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !jQuery.support.optSelected ) {
+       jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
+               get: function( elem ) {
+                       var parent = elem.parentNode;
+
+                       if ( parent ) {
+                               parent.selectedIndex;
+
+                               // Make sure that it also works with optgroups, see #5701
+                               if ( parent.parentNode ) {
+                                       parent.parentNode.selectedIndex;
+                               }
+                       }
+                       return null;
+               }
+       });
+}
+
+// IE6/7 call enctype encoding
+if ( !jQuery.support.enctype ) {
+       jQuery.propFix.enctype = "encoding";
+}
+
+// Radios and checkboxes getter/setter
+if ( !jQuery.support.checkOn ) {
+       jQuery.each([ "radio", "checkbox" ], function() {
+               jQuery.valHooks[ this ] = {
+                       get: function( elem ) {
+                               // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
+                               return elem.getAttribute("value") === null ? "on" : elem.value;
+                       }
+               };
+       });
+}
+jQuery.each([ "radio", "checkbox" ], function() {
+       jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
+               set: function( elem, value ) {
+                       if ( jQuery.isArray( value ) ) {
+                               return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+                       }
+               }
+       });
+});
+
+
+
+
+var rformElems = /^(?:textarea|input|select)$/i,
+       rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
+       rhoverHack = /\bhover(\.\S+)?\b/,
+       rkeyEvent = /^key/,
+       rmouseEvent = /^(?:mouse|contextmenu)|click/,
+       rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+       rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
+       quickParse = function( selector ) {
+               var quick = rquickIs.exec( selector );
+               if ( quick ) {
+                       //   0  1    2   3
+                       // [ _, tag, id, class ]
+                       quick[1] = ( quick[1] || "" ).toLowerCase();
+                       quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
+               }
+               return quick;
+       },
+       quickIs = function( elem, m ) {
+               var attrs = elem.attributes || {};
+               return (
+                       (!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
+                       (!m[2] || (attrs.id || {}).value === m[2]) &&
+                       (!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
+               );
+       },
+       hoverHack = function( events ) {
+               return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
+       };
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+       add: function( elem, types, handler, data, selector ) {
+
+               var elemData, eventHandle, events,
+                       t, tns, type, namespaces, handleObj,
+                       handleObjIn, quick, handlers, special;
+
+               // Don't attach events to noData or text/comment nodes (allow plain objects tho)
+               if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
+                       return;
+               }
+
+               // Caller can pass in an object of custom data in lieu of the handler
+               if ( handler.handler ) {
+                       handleObjIn = handler;
+                       handler = handleObjIn.handler;
+               }
+
+               // Make sure that the handler has a unique ID, used to find/remove it later
+               if ( !handler.guid ) {
+                       handler.guid = jQuery.guid++;
+               }
+
+               // Init the element's event structure and main handler, if this is the first
+               events = elemData.events;
+               if ( !events ) {
+                       elemData.events = events = {};
+               }
+               eventHandle = elemData.handle;
+               if ( !eventHandle ) {
+                       elemData.handle = eventHandle = function( e ) {
+                               // Discard the second event of a jQuery.event.trigger() and
+                               // when an event is called after a page has unloaded
+                               return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
+                                       jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+                                       undefined;
+                       };
+                       // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+                       eventHandle.elem = elem;
+               }
+
+               // Handle multiple events separated by a space
+               // jQuery(...).bind("mouseover mouseout", fn);
+               types = jQuery.trim( hoverHack(types) ).split( " " );
+               for ( t = 0; t < types.length; t++ ) {
+
+                       tns = rtypenamespace.exec( types[t] ) || [];
+                       type = tns[1];
+                       namespaces = ( tns[2] || "" ).split( "." ).sort();
+
+                       // If event changes its type, use the special event handlers for the changed type
+                       special = jQuery.event.special[ type ] || {};
+
+                       // If selector defined, determine special event api type, otherwise given type
+                       type = ( selector ? special.delegateType : special.bindType ) || type;
+
+                       // Update special based on newly reset type
+                       special = jQuery.event.special[ type ] || {};
+
+                       // handleObj is passed to all event handlers
+                       handleObj = jQuery.extend({
+                               type: type,
+                               origType: tns[1],
+                               data: data,
+                               handler: handler,
+                               guid: handler.guid,
+                               selector: selector,
+                               quick: quickParse( selector ),
+                               namespace: namespaces.join(".")
+                       }, handleObjIn );
+
+                       // Init the event handler queue if we're the first
+                       handlers = events[ type ];
+                       if ( !handlers ) {
+                               handlers = events[ type ] = [];
+                               handlers.delegateCount = 0;
+
+                               // Only use addEventListener/attachEvent if the special events handler returns false
+                               if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+                                       // Bind the global event handler to the element
+                                       if ( elem.addEventListener ) {
+                                               elem.addEventListener( type, eventHandle, false );
+
+                                       } else if ( elem.attachEvent ) {
+                                               elem.attachEvent( "on" + type, eventHandle );
+                                       }
+                               }
+                       }
+
+                       if ( special.add ) {
+                               special.add.call( elem, handleObj );
+
+                               if ( !handleObj.handler.guid ) {
+                                       handleObj.handler.guid = handler.guid;
+                               }
+                       }
+
+                       // Add to the element's handler list, delegates in front
+                       if ( selector ) {
+                               handlers.splice( handlers.delegateCount++, 0, handleObj );
+                       } else {
+                               handlers.push( handleObj );
+                       }
+
+                       // Keep track of which events have ever been used, for event optimization
+                       jQuery.event.global[ type ] = true;
+               }
+
+               // Nullify elem to prevent memory leaks in IE
+               elem = null;
+       },
+
+       global: {},
+
+       // Detach an event or set of events from an element
+       remove: function( elem, types, handler, selector, mappedTypes ) {
+
+               var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
+                       t, tns, type, origType, namespaces, origCount,
+                       j, events, special, handle, eventType, handleObj;
+
+               if ( !elemData || !(events = elemData.events) ) {
+                       return;
+               }
+
+               // Once for each type.namespace in types; type may be omitted
+               types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
+               for ( t = 0; t < types.length; t++ ) {
+                       tns = rtypenamespace.exec( types[t] ) || [];
+                       type = origType = tns[1];
+                       namespaces = tns[2];
+
+                       // Unbind all events (on this namespace, if provided) for the element
+                       if ( !type ) {
+                               for ( type in events ) {
+                                       jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+                               }
+                               continue;
+                       }
+
+                       special = jQuery.event.special[ type ] || {};
+                       type = ( selector? special.delegateType : special.bindType ) || type;
+                       eventType = events[ type ] || [];
+                       origCount = eventType.length;
+                       namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+
+                       // Remove matching events
+                       for ( j = 0; j < eventType.length; j++ ) {
+                               handleObj = eventType[ j ];
+
+                               if ( ( mappedTypes || origType === handleObj.origType ) &&
+                                        ( !handler || handler.guid === handleObj.guid ) &&
+                                        ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
+                                        ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+                                       eventType.splice( j--, 1 );
+
+                                       if ( handleObj.selector ) {
+                                               eventType.delegateCount--;
+                                       }
+                                       if ( special.remove ) {
+                                               special.remove.call( elem, handleObj );
+                                       }
+                               }
+                       }
+
+                       // Remove generic event handler if we removed something and no more handlers exist
+                       // (avoids potential for endless recursion during removal of special event handlers)
+                       if ( eventType.length === 0 && origCount !== eventType.length ) {
+                               if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
+                                       jQuery.removeEvent( elem, type, elemData.handle );
+                               }
+
+                               delete events[ type ];
+                       }
+               }
+
+               // Remove the expando if it's no longer used
+               if ( jQuery.isEmptyObject( events ) ) {
+                       handle = elemData.handle;
+                       if ( handle ) {
+                               handle.elem = null;
+                       }
+
+                       // removeData also checks for emptiness and clears the expando if empty
+                       // so use it instead of delete
+                       jQuery.removeData( elem, [ "events", "handle" ], true );
+               }
+       },
+
+       // Events that are safe to short-circuit if no handlers are attached.
+       // Native DOM events should not be added, they may have inline handlers.
+       customEvent: {
+               "getData": true,
+               "setData": true,
+               "changeData": true
+       },
+
+       trigger: function( event, data, elem, onlyHandlers ) {
+               // Don't do events on text and comment nodes
+               if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
+                       return;
+               }
+
+               // Event object or event type
+               var type = event.type || event,
+                       namespaces = [],
+                       cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;
+
+               // focus/blur morphs to focusin/out; ensure we're not firing them right now
+               if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+                       return;
+               }
+
+               if ( type.indexOf( "!" ) >= 0 ) {
+                       // Exclusive events trigger only for the exact event (no namespaces)
+                       type = type.slice(0, -1);
+                       exclusive = true;
+               }
+
+               if ( type.indexOf( "." ) >= 0 ) {
+                       // Namespaced trigger; create a regexp to match event type in handle()
+                       namespaces = type.split(".");
+                       type = namespaces.shift();
+                       namespaces.sort();
+               }
+
+               if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
+                       // No jQuery handlers for this event type, and it can't have inline handlers
+                       return;
+               }
+
+               // Caller can pass in an Event, Object, or just an event type string
+               event = typeof event === "object" ?
+                       // jQuery.Event object
+                       event[ jQuery.expando ] ? event :
+                       // Object literal
+                       new jQuery.Event( type, event ) :
+                       // Just the event type (string)
+                       new jQuery.Event( type );
+
+               event.type = type;
+               event.isTrigger = true;
+               event.exclusive = exclusive;
+               event.namespace = namespaces.join( "." );
+               event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
+               ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";
+
+               // Handle a global trigger
+               if ( !elem ) {
+
+                       // TODO: Stop taunting the data cache; remove global events and always attach to document
+                       cache = jQuery.cache;
+                       for ( i in cache ) {
+                               if ( cache[ i ].events && cache[ i ].events[ type ] ) {
+                                       jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
+                               }
+                       }
+                       return;
+               }
+
+               // Clean up the event in case it is being reused
+               event.result = undefined;
+               if ( !event.target ) {
+                       event.target = elem;
+               }
+
+               // Clone any incoming data and prepend the event, creating the handler arg list
+               data = data != null ? jQuery.makeArray( data ) : [];
+               data.unshift( event );
+
+               // Allow special events to draw outside the lines
+               special = jQuery.event.special[ type ] || {};
+               if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
+                       return;
+               }
+
+               // Determine event propagation path in advance, per W3C events spec (#9951)
+               // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+               eventPath = [[ elem, special.bindType || type ]];
+               if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+                       bubbleType = special.delegateType || type;
+                       cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
+                       old = null;
+                       for ( ; cur; cur = cur.parentNode ) {
+                               eventPath.push([ cur, bubbleType ]);
+                               old = cur;
+                       }
+
+                       // Only add window if we got to document (e.g., not plain obj or detached DOM)
+                       if ( old && old === elem.ownerDocument ) {
+                               eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
+                       }
+               }
+
+               // Fire handlers on the event path
+               for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {
+
+                       cur = eventPath[i][0];
+                       event.type = eventPath[i][1];
+
+                       handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+                       if ( handle ) {
+                               handle.apply( cur, data );
+                       }
+                       // Note that this is a bare JS function and not a jQuery handler
+                       handle = ontype && cur[ ontype ];
+                       if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
+                               event.preventDefault();
+                       }
+               }
+               event.type = type;
+
+               // If nobody prevented the default action, do it now
+               if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+                       if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
+                               !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
+
+                               // Call a native DOM method on the target with the same name name as the event.
+                               // Can't use an .isFunction() check here because IE6/7 fails that test.
+                               // Don't do default actions on window, that's where global variables be (#6170)
+                               // IE<9 dies on focus/blur to hidden element (#1486)
+                               if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {
+
+                                       // Don't re-trigger an onFOO event when we call its FOO() method
+                                       old = elem[ ontype ];
+
+                                       if ( old ) {
+                                               elem[ ontype ] = null;
+                                       }
+
+                                       // Prevent re-triggering of the same event, since we already bubbled it above
+                                       jQuery.event.triggered = type;
+                                       elem[ type ]();
+                                       jQuery.event.triggered = undefined;
+
+                                       if ( old ) {
+                                               elem[ ontype ] = old;
+                                       }
+                               }
+                       }
+               }
+
+               return event.result;
+       },
+
+       dispatch: function( event ) {
+
+               // Make a writable jQuery.Event from the native event object
+               event = jQuery.event.fix( event || window.event );
+
+               var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
+                       delegateCount = handlers.delegateCount,
+                       args = [].slice.call( arguments, 0 ),
+                       run_all = !event.exclusive && !event.namespace,
+                       handlerQueue = [],
+                       i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;
+
+               // Use the fix-ed jQuery.Event rather than the (read-only) native event
+               args[0] = event;
+               event.delegateTarget = this;
+
+               // Determine handlers that should run if there are delegated events
+               // Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
+               if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {
+
+                       // Pregenerate a single jQuery object for reuse with .is()
+                       jqcur = jQuery(this);
+                       jqcur.context = this.ownerDocument || this;
+
+                       for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
+                               selMatch = {};
+                               matches = [];
+                               jqcur[0] = cur;
+                               for ( i = 0; i < delegateCount; i++ ) {
+                                       handleObj = handlers[ i ];
+                                       sel = handleObj.selector;
+
+                                       if ( selMatch[ sel ] === undefined ) {
+                                               selMatch[ sel ] = (
+                                                       handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
+                                               );
+                                       }
+                                       if ( selMatch[ sel ] ) {
+                                               matches.push( handleObj );
+                                       }
+                               }
+                               if ( matches.length ) {
+                                       handlerQueue.push({ elem: cur, matches: matches });
+                               }
+                       }
+               }
+
+               // Add the remaining (directly-bound) handlers
+               if ( handlers.length > delegateCount ) {
+                       handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
+               }
+
+               // Run delegates first; they may want to stop propagation beneath us
+               for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
+                       matched = handlerQueue[ i ];
+                       event.currentTarget = matched.elem;
+
+                       for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
+                               handleObj = matched.matches[ j ];
+
+                               // Triggered event must either 1) be non-exclusive and have no namespace, or
+                               // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+                               if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {
+
+                                       event.data = handleObj.data;
+                                       event.handleObj = handleObj;
+
+                                       ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+                                                       .apply( matched.elem, args );
+
+                                       if ( ret !== undefined ) {
+                                               event.result = ret;
+                                               if ( ret === false ) {
+                                                       event.preventDefault();
+                                                       event.stopPropagation();
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return event.result;
+       },
+
+       // Includes some event props shared by KeyEvent and MouseEvent
+       // *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
+       props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+       fixHooks: {},
+
+       keyHooks: {
+               props: "char charCode key keyCode".split(" "),
+               filter: function( event, original ) {
+
+                       // Add which for key events
+                       if ( event.which == null ) {
+                               event.which = original.charCode != null ? original.charCode : original.keyCode;
+                       }
+
+                       return event;
+               }
+       },
+
+       mouseHooks: {
+               props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+               filter: function( event, original ) {
+                       var eventDoc, doc, body,
+                               button = original.button,
+                               fromElement = original.fromElement;
+
+                       // Calculate pageX/Y if missing and clientX/Y available
+                       if ( event.pageX == null && original.clientX != null ) {
+                               eventDoc = event.target.ownerDocument || document;
+                               doc = eventDoc.documentElement;
+                               body = eventDoc.body;
+
+                               event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+                               event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
+                       }
+
+                       // Add relatedTarget, if necessary
+                       if ( !event.relatedTarget && fromElement ) {
+                               event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+                       }
+
+                       // Add which for click: 1 === left; 2 === middle; 3 === right
+                       // Note: button is not normalized, so don't use it
+                       if ( !event.which && button !== undefined ) {
+                               event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+                       }
+
+                       return event;
+               }
+       },
+
+       fix: function( event ) {
+               if ( event[ jQuery.expando ] ) {
+                       return event;
+               }
+
+               // Create a writable copy of the event object and normalize some properties
+               var i, prop,
+                       originalEvent = event,
+                       fixHook = jQuery.event.fixHooks[ event.type ] || {},
+                       copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+               event = jQuery.Event( originalEvent );
+
+               for ( i = copy.length; i; ) {
+                       prop = copy[ --i ];
+                       event[ prop ] = originalEvent[ prop ];
+               }
+
+               // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
+               if ( !event.target ) {
+                       event.target = originalEvent.srcElement || document;
+               }
+
+               // Target should not be a text node (#504, Safari)
+               if ( event.target.nodeType === 3 ) {
+                       event.target = event.target.parentNode;
+               }
+
+               // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
+               if ( event.metaKey === undefined ) {
+                       event.metaKey = event.ctrlKey;
+               }
+
+               return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+       },
+
+       special: {
+               ready: {
+                       // Make sure the ready event is setup
+                       setup: jQuery.bindReady
+               },
+
+               load: {
+                       // Prevent triggered image.load events from bubbling to window.load
+                       noBubble: true
+               },
+
+               focus: {
+                       delegateType: "focusin"
+               },
+               blur: {
+                       delegateType: "focusout"
+               },
+
+               beforeunload: {
+                       setup: function( data, namespaces, eventHandle ) {
+                               // We only want to do this special case on windows
+                               if ( jQuery.isWindow( this ) ) {
+                                       this.onbeforeunload = eventHandle;
+                               }
+                       },
+
+                       teardown: function( namespaces, eventHandle ) {
+                               if ( this.onbeforeunload === eventHandle ) {
+                                       this.onbeforeunload = null;
+                               }
+                       }
+               }
+       },
+
+       simulate: function( type, elem, event, bubble ) {
+               // Piggyback on a donor event to simulate a different one.
+               // Fake originalEvent to avoid donor's stopPropagation, but if the
+               // simulated event prevents default then we do the same on the donor.
+               var e = jQuery.extend(
+                       new jQuery.Event(),
+                       event,
+                       { type: type,
+                               isSimulated: true,
+                               originalEvent: {}
+                       }
+               );
+               if ( bubble ) {
+                       jQuery.event.trigger( e, null, elem );
+               } else {
+                       jQuery.event.dispatch.call( elem, e );
+               }
+               if ( e.isDefaultPrevented() ) {
+                       event.preventDefault();
+               }
+       }
+};
+
+// Some plugins are using, but it's undocumented/deprecated and will be removed.
+// The 1.7 special event interface should provide all the hooks needed now.
+jQuery.event.handle = jQuery.event.dispatch;
+
+jQuery.removeEvent = document.removeEventListener ?
+       function( elem, type, handle ) {
+               if ( elem.removeEventListener ) {
+                       elem.removeEventListener( type, handle, false );
+               }
+       } :
+       function( elem, type, handle ) {
+               if ( elem.detachEvent ) {
+                       elem.detachEvent( "on" + type, handle );
+               }
+       };
+
+jQuery.Event = function( src, props ) {
+       // Allow instantiation without the 'new' keyword
+       if ( !(this instanceof jQuery.Event) ) {
+               return new jQuery.Event( src, props );
+       }
+
+       // Event object
+       if ( src && src.type ) {
+               this.originalEvent = src;
+               this.type = src.type;
+
+               // Events bubbling up the document may have been marked as prevented
+               // by a handler lower down the tree; reflect the correct value.
+               this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
+                       src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+       // Event type
+       } else {
+               this.type = src;
+       }
+
+       // Put explicitly provided properties onto the event object
+       if ( props ) {
+               jQuery.extend( this, props );
+       }
+
+       // Create a timestamp if incoming event doesn't have one
+       this.timeStamp = src && src.timeStamp || jQuery.now();
+
+       // Mark it as fixed
+       this[ jQuery.expando ] = true;
+};
+
+function returnFalse() {
+       return false;
+}
+function returnTrue() {
+       return true;
+}
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+       preventDefault: function() {
+               this.isDefaultPrevented = returnTrue;
+
+               var e = this.originalEvent;
+               if ( !e ) {
+                       return;
+               }
+
+               // if preventDefault exists run it on the original event
+               if ( e.preventDefault ) {
+                       e.preventDefault();
+
+               // otherwise set the returnValue property of the original event to false (IE)
+               } else {
+                       e.returnValue = false;
+               }
+       },
+       stopPropagation: function() {
+               this.isPropagationStopped = returnTrue;
+
+               var e = this.originalEvent;
+               if ( !e ) {
+                       return;
+               }
+               // if stopPropagation exists run it on the original event
+               if ( e.stopPropagation ) {
+                       e.stopPropagation();
+               }
+               // otherwise set the cancelBubble property of the original event to true (IE)
+               e.cancelBubble = true;
+       },
+       stopImmediatePropagation: function() {
+               this.isImmediatePropagationStopped = returnTrue;
+               this.stopPropagation();
+       },
+       isDefaultPrevented: returnFalse,
+       isPropagationStopped: returnFalse,
+       isImmediatePropagationStopped: returnFalse
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+       mouseenter: "mouseover",
+       mouseleave: "mouseout"
+}, function( orig, fix ) {
+       jQuery.event.special[ orig ] = {
+               delegateType: fix,
+               bindType: fix,
+
+               handle: function( event ) {
+                       var target = this,
+                               related = event.relatedTarget,
+                               handleObj = event.handleObj,
+                               selector = handleObj.selector,
+                               ret;
+
+                       // For mousenter/leave call the handler if related is outside the target.
+                       // NB: No relatedTarget if the mouse left/entered the browser window
+                       if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+                               event.type = handleObj.origType;
+                               ret = handleObj.handler.apply( this, arguments );
+                               event.type = fix;
+                       }
+                       return ret;
+               }
+       };
+});
+
+// IE submit delegation
+if ( !jQuery.support.submitBubbles ) {
+
+       jQuery.event.special.submit = {
+               setup: function() {
+                       // Only need this for delegated form submit events
+                       if ( jQuery.nodeName( this, "form" ) ) {
+                               return false;
+                       }
+
+                       // Lazy-add a submit handler when a descendant form may potentially be submitted
+                       jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+                               // Node name check avoids a VML-related crash in IE (#9807)
+                               var elem = e.target,
+                                       form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+                               if ( form && !form._submit_attached ) {
+                                       jQuery.event.add( form, "submit._submit", function( event ) {
+                                               // If form was submitted by the user, bubble the event up the tree
+                                               if ( this.parentNode && !event.isTrigger ) {
+                                                       jQuery.event.simulate( "submit", this.parentNode, event, true );
+                                               }
+                                       });
+                                       form._submit_attached = true;
+                               }
+                       });
+                       // return undefined since we don't need an event listener
+               },
+
+               teardown: function() {
+                       // Only need this for delegated form submit events
+                       if ( jQuery.nodeName( this, "form" ) ) {
+                               return false;
+                       }
+
+                       // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+                       jQuery.event.remove( this, "._submit" );
+               }
+       };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !jQuery.support.changeBubbles ) {
+
+       jQuery.event.special.change = {
+
+               setup: function() {
+
+                       if ( rformElems.test( this.nodeName ) ) {
+                               // IE doesn't fire change on a check/radio until blur; trigger it on click
+                               // after a propertychange. Eat the blur-change in special.change.handle.
+                               // This still fires onchange a second time for check/radio after blur.
+                               if ( this.type === "checkbox" || this.type === "radio" ) {
+                                       jQuery.event.add( this, "propertychange._change", function( event ) {
+                                               if ( event.originalEvent.propertyName === "checked" ) {
+                                                       this._just_changed = true;
+                                               }
+                                       });
+                                       jQuery.event.add( this, "click._change", function( event ) {
+                                               if ( this._just_changed && !event.isTrigger ) {
+                                                       this._just_changed = false;
+                                                       jQuery.event.simulate( "change", this, event, true );
+                                               }
+                                       });
+                               }
+                               return false;
+                       }
+                       // Delegated event; lazy-add a change handler on descendant inputs
+                       jQuery.event.add( this, "beforeactivate._change", function( e ) {
+                               var elem = e.target;
+
+                               if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
+                                       jQuery.event.add( elem, "change._change", function( event ) {
+                                               if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+                                                       jQuery.event.simulate( "change", this.parentNode, event, true );
+                                               }
+                                       });
+                                       elem._change_attached = true;
+                               }
+                       });
+               },
+
+               handle: function( event ) {
+                       var elem = event.target;
+
+                       // Swallow native change events from checkbox/radio, we already triggered them above
+                       if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+                               return event.handleObj.handler.apply( this, arguments );
+                       }
+               },
+
+               teardown: function() {
+                       jQuery.event.remove( this, "._change" );
+
+                       return rformElems.test( this.nodeName );
+               }
+       };
+}
+
+// Create "bubbling" focus and blur events
+if ( !jQuery.support.focusinBubbles ) {
+       jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+               // Attach a single capturing handler while someone wants focusin/focusout
+               var attaches = 0,
+                       handler = function( event ) {
+                               jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+                       };
+
+               jQuery.event.special[ fix ] = {
+                       setup: function() {
+                               if ( attaches++ === 0 ) {
+                                       document.addEventListener( orig, handler, true );
+                               }
+                       },
+                       teardown: function() {
+                               if ( --attaches === 0 ) {
+                                       document.removeEventListener( orig, handler, true );
+                               }
+                       }
+               };
+       });
+}
+
+jQuery.fn.extend({
+
+       on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+               var origFn, type;
+
+               // Types can be a map of types/handlers
+               if ( typeof types === "object" ) {
+                       // ( types-Object, selector, data )
+                       if ( typeof selector !== "string" ) {
+                               // ( types-Object, data )
+                               data = selector;
+                               selector = undefined;
+                       }
+                       for ( type in types ) {
+                               this.on( type, selector, data, types[ type ], one );
+                       }
+                       return this;
+               }
+
+               if ( data == null && fn == null ) {
+                       // ( types, fn )
+                       fn = selector;
+                       data = selector = undefined;
+               } else if ( fn == null ) {
+                       if ( typeof selector === "string" ) {
+                               // ( types, selector, fn )
+                               fn = data;
+                               data = undefined;
+                       } else {
+                               // ( types, data, fn )
+                               fn = data;
+                               data = selector;
+                               selector = undefined;
+                       }
+               }
+               if ( fn === false ) {
+                       fn = returnFalse;
+               } else if ( !fn ) {
+                       return this;
+               }
+
+               if ( one === 1 ) {
+                       origFn = fn;
+                       fn = function( event ) {
+                               // Can use an empty set, since event contains the info
+                               jQuery().off( event );
+                               return origFn.apply( this, arguments );
+                       };
+                       // Use same guid so caller can remove using origFn
+                       fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+               }
+               return this.each( function() {
+                       jQuery.event.add( this, types, fn, data, selector );
+               });
+       },
+       one: function( types, selector, data, fn ) {
+               return this.on.call( this, types, selector, data, fn, 1 );
+       },
+       off: function( types, selector, fn ) {
+               if ( types && types.preventDefault && types.handleObj ) {
+                       // ( event )  dispatched jQuery.Event
+                       var handleObj = types.handleObj;
+                       jQuery( types.delegateTarget ).off(
+                               handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
+                               handleObj.selector,
+                               handleObj.handler
+                       );
+                       return this;
+               }
+               if ( typeof types === "object" ) {
+                       // ( types-object [, selector] )
+                       for ( var type in types ) {
+                               this.off( type, selector, types[ type ] );
+                       }
+                       return this;
+               }
+               if ( selector === false || typeof selector === "function" ) {
+                       // ( types [, fn] )
+                       fn = selector;
+                       selector = undefined;
+               }
+               if ( fn === false ) {
+                       fn = returnFalse;
+               }
+               return this.each(function() {
+                       jQuery.event.remove( this, types, fn, selector );
+               });
+       },
+
+       bind: function( types, data, fn ) {
+               return this.on( types, null, data, fn );
+       },
+       unbind: function( types, fn ) {
+               return this.off( types, null, fn );
+       },
+
+       live: function( types, data, fn ) {
+               jQuery( this.context ).on( types, this.selector, data, fn );
+               return this;
+       },
+       die: function( types, fn ) {
+               jQuery( this.context ).off( types, this.selector || "**", fn );
+               return this;
+       },
+
+       delegate: function( selector, types, data, fn ) {
+               return this.on( types, selector, data, fn );
+       },
+       undelegate: function( selector, types, fn ) {
+               // ( namespace ) or ( selector, types [, fn] )
+               return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
+       },
+
+       trigger: function( type, data ) {
+               return this.each(function() {
+                       jQuery.event.trigger( type, data, this );
+               });
+       },
+       triggerHandler: function( type, data ) {
+               if ( this[0] ) {
+                       return jQuery.event.trigger( type, data, this[0], true );
+               }
+       },
+
+       toggle: function( fn ) {
+               // Save reference to arguments for access in closure
+               var args = arguments,
+                       guid = fn.guid || jQuery.guid++,
+                       i = 0,
+                       toggler = function( event ) {
+                               // Figure out which function to execute
+                               var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
+                               jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
+
+                               // Make sure that clicks stop
+                               event.preventDefault();
+
+                               // and execute the function
+                               return args[ lastToggle ].apply( this, arguments ) || false;
+                       };
+
+               // link all the functions, so any of them can unbind this click handler
+               toggler.guid = guid;
+               while ( i < args.length ) {
+                       args[ i++ ].guid = guid;
+               }
+
+               return this.click( toggler );
+       },
+
+       hover: function( fnOver, fnOut ) {
+               return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+       }
+});
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+       "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+       "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+       // Handle event binding
+       jQuery.fn[ name ] = function( data, fn ) {
+               if ( fn == null ) {
+                       fn = data;
+                       data = null;
+               }
+
+               return arguments.length > 0 ?
+                       this.on( name, null, data, fn ) :
+                       this.trigger( name );
+       };
+
+       if ( jQuery.attrFn ) {
+               jQuery.attrFn[ name ] = true;
+       }
+
+       if ( rkeyEvent.test( name ) ) {
+               jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
+       }
+
+       if ( rmouseEvent.test( name ) ) {
+               jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
+       }
+});
+
+
+
+/*!
+ * Sizzle CSS Selector Engine
+ *  Copyright 2011, The Dojo Foundation
+ *  Released under the MIT, BSD, and GPL Licenses.
+ *  More information: http://sizzlejs.com/
+ */
+(function(){
+
+var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+       expando = "sizcache" + (Math.random() + '').replace('.', ''),
+       done = 0,
+       toString = Object.prototype.toString,
+       hasDuplicate = false,
+       baseHasDuplicate = true,
+       rBackslash = /\\/g,
+       rReturn = /\r\n/g,
+       rNonWord = /\W/;
+
+// Here we check if the JavaScript engine is using some sort of
+// optimization where it does not always call our comparision
+// function. If that is the case, discard the hasDuplicate value.
+//   Thus far that includes Google Chrome.
+[0, 0].sort(function() {
+       baseHasDuplicate = false;
+       return 0;
+});
+
+var Sizzle = function( selector, context, results, seed ) {
+       results = results || [];
+       context = context || document;
+
+       var origContext = context;
+
+       if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
+               return [];
+       }
+       
+       if ( !selector || typeof selector !== "string" ) {
+               return results;
+       }
+
+       var m, set, checkSet, extra, ret, cur, pop, i,
+               prune = true,
+               contextXML = Sizzle.isXML( context ),
+               parts = [],
+               soFar = selector;
+       
+       // Reset the position of the chunker regexp (start from head)
+       do {
+               chunker.exec( "" );
+               m = chunker.exec( soFar );
+
+               if ( m ) {
+                       soFar = m[3];
+               
+                       parts.push( m[1] );
+               
+                       if ( m[2] ) {
+                               extra = m[3];
+                               break;
+                       }
+               }
+       } while ( m );
+
+       if ( parts.length > 1 && origPOS.exec( selector ) ) {
+
+               if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
+                       set = posProcess( parts[0] + parts[1], context, seed );
+
+               } else {
+                       set = Expr.relative[ parts[0] ] ?
+                               [ context ] :
+                               Sizzle( parts.shift(), context );
+
+                       while ( parts.length ) {
+                               selector = parts.shift();
+
+                               if ( Expr.relative[ selector ] ) {
+                                       selector += parts.shift();
+                               }
+                               
+                               set = posProcess( selector, set, seed );
+                       }
+               }
+
+       } else {
+               // Take a shortcut and set the context if the root selector is an ID
+               // (but not if it'll be faster if the inner selector is an ID)
+               if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
+                               Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
+
+                       ret = Sizzle.find( parts.shift(), context, contextXML );
+                       context = ret.expr ?
+                               Sizzle.filter( ret.expr, ret.set )[0] :
+                               ret.set[0];
+               }
+
+               if ( context ) {
+                       ret = seed ?
+                               { expr: parts.pop(), set: makeArray(seed) } :
+                               Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
+
+                       set = ret.expr ?
+                               Sizzle.filter( ret.expr, ret.set ) :
+                               ret.set;
+
+                       if ( parts.length > 0 ) {
+                               checkSet = makeArray( set );
+
+                       } else {
+                               prune = false;
+                       }
+
+                       while ( parts.length ) {
+                               cur = parts.pop();
+                               pop = cur;
+
+                               if ( !Expr.relative[ cur ] ) {
+                                       cur = "";
+                               } else {
+                                       pop = parts.pop();
+                               }
+
+                               if ( pop == null ) {
+                                       pop = context;
+                               }
+
+                               Expr.relative[ cur ]( checkSet, pop, contextXML );
+                       }
+
+               } else {
+                       checkSet = parts = [];
+               }
+       }
+
+       if ( !checkSet ) {
+               checkSet = set;
+       }
+
+       if ( !checkSet ) {
+               Sizzle.error( cur || selector );
+       }
+
+       if ( toString.call(checkSet) === "[object Array]" ) {
+               if ( !prune ) {
+                       results.push.apply( results, checkSet );
+
+               } else if ( context && context.nodeType === 1 ) {
+                       for ( i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
+                                       results.push( set[i] );
+                               }
+                       }
+
+               } else {
+                       for ( i = 0; checkSet[i] != null; i++ ) {
+                               if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
+                                       results.push( set[i] );
+                               }
+                       }
+               }
+
+       } else {
+               makeArray( checkSet, results );
+       }
+
+       if ( extra ) {
+               Sizzle( extra, origContext, results, seed );
+               Sizzle.uniqueSort( results );
+       }
+
+       return results;
+};
+
+Sizzle.uniqueSort = function( results ) {
+       if ( sortOrder ) {
+               hasDuplicate = baseHasDuplicate;
+               results.sort( sortOrder );
+
+               if ( hasDuplicate ) {
+                       for ( var i = 1; i < results.length; i++ ) {
+                               if ( results[i] === results[ i - 1 ] ) {
+                                       results.splice( i--, 1 );
+                               }
+                       }
+               }
+       }
+
+       return results;
+};
+
+Sizzle.matches = function( expr, set ) {
+       return Sizzle( expr, null, null, set );
+};
+
+Sizzle.matchesSelector = function( node, expr ) {
+       return Sizzle( expr, null, null, [node] ).length > 0;
+};
+
+Sizzle.find = function( expr, context, isXML ) {
+       var set, i, len, match, type, left;
+
+       if ( !expr ) {
+               return [];
+       }
+
+       for ( i = 0, len = Expr.order.length; i < len; i++ ) {
+               type = Expr.order[i];
+               
+               if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
+                       left = match[1];
+                       match.splice( 1, 1 );
+
+                       if ( left.substr( left.length - 1 ) !== "\\" ) {
+                               match[1] = (match[1] || "").replace( rBackslash, "" );
+                               set = Expr.find[ type ]( match, context, isXML );
+
+                               if ( set != null ) {
+                                       expr = expr.replace( Expr.match[ type ], "" );
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if ( !set ) {
+               set = typeof context.getElementsByTagName !== "undefined" ?
+                       context.getElementsByTagName( "*" ) :
+                       [];
+       }
+
+       return { set: set, expr: expr };
+};
+
+Sizzle.filter = function( expr, set, inplace, not ) {
+       var match, anyFound,
+               type, found, item, filter, left,
+               i, pass,
+               old = expr,
+               result = [],
+               curLoop = set,
+               isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
+
+       while ( expr && set.length ) {
+               for ( type in Expr.filter ) {
+                       if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
+                               filter = Expr.filter[ type ];
+                               left = match[1];
+
+                               anyFound = false;
+
+                               match.splice(1,1);
+
+                               if ( left.substr( left.length - 1 ) === "\\" ) {
+                                       continue;
+                               }
+
+                               if ( curLoop === result ) {
+                                       result = [];
+                               }
+
+                               if ( Expr.preFilter[ type ] ) {
+                                       match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
+
+                                       if ( !match ) {
+                                               anyFound = found = true;
+
+                                       } else if ( match === true ) {
+                                               continue;
+                                       }
+                               }
+
+                               if ( match ) {
+                                       for ( i = 0; (item = curLoop[i]) != null; i++ ) {
+                                               if ( item ) {
+                                                       found = filter( item, match, i, curLoop );
+                                                       pass = not ^ found;
+
+                                                       if ( inplace && found != null ) {
+                                                               if ( pass ) {
+                                                                       anyFound = true;
+
+                                                               } else {
+                                                                       curLoop[i] = false;
+                                                               }
+
+                                                       } else if ( pass ) {
+                                                               result.push( item );
+                                                               anyFound = true;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               if ( found !== undefined ) {
+                                       if ( !inplace ) {
+                                               curLoop = result;
+                                       }
+
+                                       expr = expr.replace( Expr.match[ type ], "" );
+
+                                       if ( !anyFound ) {
+                                               return [];
+                                       }
+
+                                       break;
+                               }
+                       }
+               }
+
+               // Improper expression
+               if ( expr === old ) {
+                       if ( anyFound == null ) {
+                               Sizzle.error( expr );
+
+                       } else {
+                               break;
+                       }
+               }
+
+               old = expr;
+       }
+
+       return curLoop;
+};
+
+Sizzle.error = function( msg ) {
+       throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Utility function for retreiving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+var getText = Sizzle.getText = function( elem ) {
+    var i, node,
+               nodeType = elem.nodeType,
+               ret = "";
+
+       if ( nodeType ) {
+               if ( nodeType === 1 || nodeType === 9 ) {
+                       // Use textContent || innerText for elements
+                       if ( typeof elem.textContent === 'string' ) {
+                               return elem.textContent;
+                       } else if ( typeof elem.innerText === 'string' ) {
+                               // Replace IE's carriage returns
+                               return elem.innerText.replace( rReturn, '' );
+                       } else {
+                               // Traverse it's children
+                               for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
+                                       ret += getText( elem );
+                               }
+                       }
+               } else if ( nodeType === 3 || nodeType === 4 ) {
+                       return elem.nodeValue;
+               }
+       } else {
+
+               // If no nodeType, this is expected to be an array
+               for ( i = 0; (node = elem[i]); i++ ) {
+                       // Do not traverse comment nodes
+                       if ( node.nodeType !== 8 ) {
+                               ret += getText( node );
+                       }
+               }
+       }
+       return ret;
+};
+
+var Expr = Sizzle.selectors = {
+       order: [ "ID", "NAME", "TAG" ],
+
+       match: {
+               ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+               CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
+               NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
+               ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
+               TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
+               CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
+               POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
+               PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
+       },
+
+       leftMatch: {},
+
+       attrMap: {
+               "class": "className",
+               "for": "htmlFor"
+       },
+
+       attrHandle: {
+               href: function( elem ) {
+                       return elem.getAttribute( "href" );
+               },
+               type: function( elem ) {
+                       return elem.getAttribute( "type" );
+               }
+       },
+
+       relative: {
+               "+": function(checkSet, part){
+                       var isPartStr = typeof part === "string",
+                               isTag = isPartStr && !rNonWord.test( part ),
+                               isPartStrNotTag = isPartStr && !isTag;
+
+                       if ( isTag ) {
+                               part = part.toLowerCase();
+                       }
+
+                       for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
+                               if ( (elem = checkSet[i]) ) {
+                                       while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
+
+                                       checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
+                                               elem || false :
+                                               elem === part;
+                               }
+                       }
+
+                       if ( isPartStrNotTag ) {
+                               Sizzle.filter( part, checkSet, true );
+                       }
+               },
+
+               ">": function( checkSet, part ) {
+                       var elem,
+                               isPartStr = typeof part === "string",
+                               i = 0,
+                               l = checkSet.length;
+
+                       if ( isPartStr && !rNonWord.test( part ) ) {
+                               part = part.toLowerCase();
+
+                               for ( ; i < l; i++ ) {
+                                       elem = checkSet[i];
+
+                                       if ( elem ) {
+                                               var parent = elem.parentNode;
+                                               checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
+                                       }
+                               }
+
+                       } else {
+                               for ( ; i < l; i++ ) {
+                                       elem = checkSet[i];
+
+                                       if ( elem ) {
+                                               checkSet[i] = isPartStr ?
+                                                       elem.parentNode :
+                                                       elem.parentNode === part;
+                                       }
+                               }
+
+                               if ( isPartStr ) {
+                                       Sizzle.filter( part, checkSet, true );
+                               }
+                       }
+               },
+
+               "": function(checkSet, part, isXML){
+                       var nodeCheck,
+                               doneName = done++,
+                               checkFn = dirCheck;
+
+                       if ( typeof part === "string" && !rNonWord.test( part ) ) {
+                               part = part.toLowerCase();
+                               nodeCheck = part;
+                               checkFn = dirNodeCheck;
+                       }
+
+                       checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
+               },
+
+               "~": function( checkSet, part, isXML ) {
+                       var nodeCheck,
+                               doneName = done++,
+                               checkFn = dirCheck;
+
+                       if ( typeof part === "string" && !rNonWord.test( part ) ) {
+                               part = part.toLowerCase();
+                               nodeCheck = part;
+                               checkFn = dirNodeCheck;
+                       }
+
+                       checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
+               }
+       },
+
+       find: {
+               ID: function( match, context, isXML ) {
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+                               // Check parentNode to catch when Blackberry 4.6 returns
+                               // nodes that are no longer in the document #6963
+                               return m && m.parentNode ? [m] : [];
+                       }
+               },
+
+               NAME: function( match, context ) {
+                       if ( typeof context.getElementsByName !== "undefined" ) {
+                               var ret = [],
+                                       results = context.getElementsByName( match[1] );
+
+                               for ( var i = 0, l = results.length; i < l; i++ ) {
+                                       if ( results[i].getAttribute("name") === match[1] ) {
+                                               ret.push( results[i] );
+                                       }
+                               }
+
+                               return ret.length === 0 ? null : ret;
+                       }
+               },
+
+               TAG: function( match, context ) {
+                       if ( typeof context.getElementsByTagName !== "undefined" ) {
+                               return context.getElementsByTagName( match[1] );
+                       }
+               }
+       },
+       preFilter: {
+               CLASS: function( match, curLoop, inplace, result, not, isXML ) {
+                       match = " " + match[1].replace( rBackslash, "" ) + " ";
+
+                       if ( isXML ) {
+                               return match;
+                       }
+
+                       for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
+                               if ( elem ) {
+                                       if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
+                                               if ( !inplace ) {
+                                                       result.push( elem );
+                                               }
+
+                                       } else if ( inplace ) {
+                                               curLoop[i] = false;
+                                       }
+                               }
+                       }
+
+                       return false;
+               },
+
+               ID: function( match ) {
+                       return match[1].replace( rBackslash, "" );
+               },
+
+               TAG: function( match, curLoop ) {
+                       return match[1].replace( rBackslash, "" ).toLowerCase();
+               },
+
+               CHILD: function( match ) {
+                       if ( match[1] === "nth" ) {
+                               if ( !match[2] ) {
+                                       Sizzle.error( match[0] );
+                               }
+
+                               match[2] = match[2].replace(/^\+|\s*/g, '');
+
+                               // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
+                               var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
+                                       match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
+                                       !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
+
+                               // calculate the numbers (first)n+(last) including if they are negative
+                               match[2] = (test[1] + (test[2] || 1)) - 0;
+                               match[3] = test[3] - 0;
+                       }
+                       else if ( match[2] ) {
+                               Sizzle.error( match[0] );
+                       }
+
+                       // TODO: Move to normal caching system
+                       match[0] = done++;
+
+                       return match;
+               },
+
+               ATTR: function( match, curLoop, inplace, result, not, isXML ) {
+                       var name = match[1] = match[1].replace( rBackslash, "" );
+                       
+                       if ( !isXML && Expr.attrMap[name] ) {
+                               match[1] = Expr.attrMap[name];
+                       }
+
+                       // Handle if an un-quoted value was used
+                       match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
+
+                       if ( match[2] === "~=" ) {
+                               match[4] = " " + match[4] + " ";
+                       }
+
+                       return match;
+               },
+
+               PSEUDO: function( match, curLoop, inplace, result, not ) {
+                       if ( match[1] === "not" ) {
+                               // If we're dealing with a complex expression, or a simple one
+                               if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
+                                       match[3] = Sizzle(match[3], null, null, curLoop);
+
+                               } else {
+                                       var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
+
+                                       if ( !inplace ) {
+                                               result.push.apply( result, ret );
+                                       }
+
+                                       return false;
+                               }
+
+                       } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
+                               return true;
+                       }
+                       
+                       return match;
+               },
+
+               POS: function( match ) {
+                       match.unshift( true );
+
+                       return match;
+               }
+       },
+       
+       filters: {
+               enabled: function( elem ) {
+                       return elem.disabled === false && elem.type !== "hidden";
+               },
+
+               disabled: function( elem ) {
+                       return elem.disabled === true;
+               },
+
+               checked: function( elem ) {
+                       return elem.checked === true;
+               },
+               
+               selected: function( elem ) {
+                       // Accessing this property makes selected-by-default
+                       // options in Safari work properly
+                       if ( elem.parentNode ) {
+                               elem.parentNode.selectedIndex;
+                       }
+                       
+                       return elem.selected === true;
+               },
+
+               parent: function( elem ) {
+                       return !!elem.firstChild;
+               },
+
+               empty: function( elem ) {
+                       return !elem.firstChild;
+               },
+
+               has: function( elem, i, match ) {
+                       return !!Sizzle( match[3], elem ).length;
+               },
+
+               header: function( elem ) {
+                       return (/h\d/i).test( elem.nodeName );
+               },
+
+               text: function( elem ) {
+                       var attr = elem.getAttribute( "type" ), type = elem.type;
+                       // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
+                       // use getAttribute instead to test this case
+                       return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
+               },
+
+               radio: function( elem ) {
+                       return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
+               },
+
+               checkbox: function( elem ) {
+                       return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
+               },
+
+               file: function( elem ) {
+                       return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
+               },
+
+               password: function( elem ) {
+                       return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
+               },
+
+               submit: function( elem ) {
+                       var name = elem.nodeName.toLowerCase();
+                       return (name === "input" || name === "button") && "submit" === elem.type;
+               },
+
+               image: function( elem ) {
+                       return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
+               },
+
+               reset: function( elem ) {
+                       var name = elem.nodeName.toLowerCase();
+                       return (name === "input" || name === "button") && "reset" === elem.type;
+               },
+
+               button: function( elem ) {
+                       var name = elem.nodeName.toLowerCase();
+                       return name === "input" && "button" === elem.type || name === "button";
+               },
+
+               input: function( elem ) {
+                       return (/input|select|textarea|button/i).test( elem.nodeName );
+               },
+
+               focus: function( elem ) {
+                       return elem === elem.ownerDocument.activeElement;
+               }
+       },
+       setFilters: {
+               first: function( elem, i ) {
+                       return i === 0;
+               },
+
+               last: function( elem, i, match, array ) {
+                       return i === array.length - 1;
+               },
+
+               even: function( elem, i ) {
+                       return i % 2 === 0;
+               },
+
+               odd: function( elem, i ) {
+                       return i % 2 === 1;
+               },
+
+               lt: function( elem, i, match ) {
+                       return i < match[3] - 0;
+               },
+
+               gt: function( elem, i, match ) {
+                       return i > match[3] - 0;
+               },
+
+               nth: function( elem, i, match ) {
+                       return match[3] - 0 === i;
+               },
+
+               eq: function( elem, i, match ) {
+                       return match[3] - 0 === i;
+               }
+       },
+       filter: {
+               PSEUDO: function( elem, match, i, array ) {
+                       var name = match[1],
+                               filter = Expr.filters[ name ];
+
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+
+                       } else if ( name === "contains" ) {
+                               return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0;
+
+                       } else if ( name === "not" ) {
+                               var not = match[3];
+
+                               for ( var j = 0, l = not.length; j < l; j++ ) {
+                                       if ( not[j] === elem ) {
+                                               return false;
+                                       }
+                               }
+
+                               return true;
+
+                       } else {
+                               Sizzle.error( name );
+                       }
+               },
+
+               CHILD: function( elem, match ) {
+                       var first, last,
+                               doneName, parent, cache,
+                               count, diff,
+                               type = match[1],
+                               node = elem;
+
+                       switch ( type ) {
+                               case "only":
+                               case "first":
+                                       while ( (node = node.previousSibling) )  {
+                                               if ( node.nodeType === 1 ) { 
+                                                       return false; 
+                                               }
+                                       }
+
+                                       if ( type === "first" ) { 
+                                               return true; 
+                                       }
+
+                                       node = elem;
+
+                               case "last":
+                                       while ( (node = node.nextSibling) )      {
+                                               if ( node.nodeType === 1 ) { 
+                                                       return false; 
+                                               }
+                                       }
+
+                                       return true;
+
+                               case "nth":
+                                       first = match[2];
+                                       last = match[3];
+
+                                       if ( first === 1 && last === 0 ) {
+                                               return true;
+                                       }
+                                       
+                                       doneName = match[0];
+                                       parent = elem.parentNode;
+       
+                                       if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
+                                               count = 0;
+                                               
+                                               for ( node = parent.firstChild; node; node = node.nextSibling ) {
+                                                       if ( node.nodeType === 1 ) {
+                                                               node.nodeIndex = ++count;
+                                                       }
+                                               } 
+
+                                               parent[ expando ] = doneName;
+                                       }
+                                       
+                                       diff = elem.nodeIndex - last;
+
+                                       if ( first === 0 ) {
+                                               return diff === 0;
+
+                                       } else {
+                                               return ( diff % first === 0 && diff / first >= 0 );
+                                       }
+                       }
+               },
+
+               ID: function( elem, match ) {
+                       return elem.nodeType === 1 && elem.getAttribute("id") === match;
+               },
+
+               TAG: function( elem, match ) {
+                       return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
+               },
+               
+               CLASS: function( elem, match ) {
+                       return (" " + (elem.className || elem.getAttribute("class")) + " ")
+                               .indexOf( match ) > -1;
+               },
+
+               ATTR: function( elem, match ) {
+                       var name = match[1],
+                               result = Sizzle.attr ?
+                                       Sizzle.attr( elem, name ) :
+                                       Expr.attrHandle[ name ] ?
+                                       Expr.attrHandle[ name ]( elem ) :
+                                       elem[ name ] != null ?
+                                               elem[ name ] :
+                                               elem.getAttribute( name ),
+                               value = result + "",
+                               type = match[2],
+                               check = match[4];
+
+                       return result == null ?
+                               type === "!=" :
+                               !type && Sizzle.attr ?
+                               result != null :
+                               type === "=" ?
+                               value === check :
+                               type === "*=" ?
+                               value.indexOf(check) >= 0 :
+                               type === "~=" ?
+                               (" " + value + " ").indexOf(check) >= 0 :
+                               !check ?
+                               value && result !== false :
+                               type === "!=" ?
+                               value !== check :
+                               type === "^=" ?
+                               value.indexOf(check) === 0 :
+                               type === "$=" ?
+                               value.substr(value.length - check.length) === check :
+                               type === "|=" ?
+                               value === check || value.substr(0, check.length + 1) === check + "-" :
+                               false;
+               },
+
+               POS: function( elem, match, i, array ) {
+                       var name = match[2],
+                               filter = Expr.setFilters[ name ];
+
+                       if ( filter ) {
+                               return filter( elem, i, match, array );
+                       }
+               }
+       }
+};
+
+var origPOS = Expr.match.POS,
+       fescape = function(all, num){
+               return "\\" + (num - 0 + 1);
+       };
+
+for ( var type in Expr.match ) {
+       Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
+       Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
+}
+
+var makeArray = function( array, results ) {
+       array = Array.prototype.slice.call( array, 0 );
+
+       if ( results ) {
+               results.push.apply( results, array );
+               return results;
+       }
+       
+       return array;
+};
+
+// Perform a simple check to determine if the browser is capable of
+// converting a NodeList to an array using builtin methods.
+// Also verifies that the returned array holds DOM nodes
+// (which is not the case in the Blackberry browser)
+try {
+       Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
+
+// Provide a fallback method if it does not work
+} catch( e ) {
+       makeArray = function( array, results ) {
+               var i = 0,
+                       ret = results || [];
+
+               if ( toString.call(array) === "[object Array]" ) {
+                       Array.prototype.push.apply( ret, array );
+
+               } else {
+                       if ( typeof array.length === "number" ) {
+                               for ( var l = array.length; i < l; i++ ) {
+                                       ret.push( array[i] );
+                               }
+
+                       } else {
+                               for ( ; array[i]; i++ ) {
+                                       ret.push( array[i] );
+                               }
+                       }
+               }
+
+               return ret;
+       };
+}
+
+var sortOrder, siblingCheck;
+
+if ( document.documentElement.compareDocumentPosition ) {
+       sortOrder = function( a, b ) {
+               if ( a === b ) {
+                       hasDuplicate = true;
+                       return 0;
+               }
+
+               if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
+                       return a.compareDocumentPosition ? -1 : 1;
+               }
+
+               return a.compareDocumentPosition(b) & 4 ? -1 : 1;
+       };
+
+} else {
+       sortOrder = function( a, b ) {
+               // The nodes are identical, we can exit early
+               if ( a === b ) {
+                       hasDuplicate = true;
+                       return 0;
+
+               // Fallback to using sourceIndex (in IE) if it's available on both nodes
+               } else if ( a.sourceIndex && b.sourceIndex ) {
+                       return a.sourceIndex - b.sourceIndex;
+               }
+
+               var al, bl,
+                       ap = [],
+                       bp = [],
+                       aup = a.parentNode,
+                       bup = b.parentNode,
+                       cur = aup;
+
+               // If the nodes are siblings (or identical) we can do a quick check
+               if ( aup === bup ) {
+                       return siblingCheck( a, b );
+
+               // If no parents were found then the nodes are disconnected
+               } else if ( !aup ) {
+                       return -1;
+
+               } else if ( !bup ) {
+                       return 1;
+               }
+
+               // Otherwise they're somewhere else in the tree so we need
+               // to build up a full list of the parentNodes for comparison
+               while ( cur ) {
+                       ap.unshift( cur );
+                       cur = cur.parentNode;
+               }
+
+               cur = bup;
+
+               while ( cur ) {
+                       bp.unshift( cur );
+                       cur = cur.parentNode;
+               }
+
+               al = ap.length;
+               bl = bp.length;
+
+               // Start walking down the tree looking for a discrepancy
+               for ( var i = 0; i < al && i < bl; i++ ) {
+                       if ( ap[i] !== bp[i] ) {
+                               return siblingCheck( ap[i], bp[i] );
+                       }
+               }
+
+               // We ended someplace up the tree so do a sibling check
+               return i === al ?
+                       siblingCheck( a, bp[i], -1 ) :
+                       siblingCheck( ap[i], b, 1 );
+       };
+
+       siblingCheck = function( a, b, ret ) {
+               if ( a === b ) {
+                       return ret;
+               }
+
+               var cur = a.nextSibling;
+
+               while ( cur ) {
+                       if ( cur === b ) {
+                               return -1;
+                       }
+
+                       cur = cur.nextSibling;
+               }
+
+               return 1;
+       };
+}
+
+// Check to see if the browser returns elements by name when
+// querying by getElementById (and provide a workaround)
+(function(){
+       // We're going to inject a fake input element with a specified name
+       var form = document.createElement("div"),
+               id = "script" + (new Date()).getTime(),
+               root = document.documentElement;
+
+       form.innerHTML = "<a name='" + id + "'/>";
+
+       // Inject it into the root element, check its status, and remove it quickly
+       root.insertBefore( form, root.firstChild );
+
+       // The workaround has to do additional checks after a getElementById
+       // Which slows things down for other browsers (hence the branching)
+       if ( document.getElementById( id ) ) {
+               Expr.find.ID = function( match, context, isXML ) {
+                       if ( typeof context.getElementById !== "undefined" && !isXML ) {
+                               var m = context.getElementById(match[1]);
+
+                               return m ?
+                                       m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
+                                               [m] :
+                                               undefined :
+                                       [];
+                       }
+               };
+
+               Expr.filter.ID = function( elem, match ) {
+                       var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+
+                       return elem.nodeType === 1 && node && node.nodeValue === match;
+               };
+       }
+
+       root.removeChild( form );
+
+       // release memory in IE
+       root = form = null;
+})();
+
+(function(){
+       // Check to see if the browser returns only elements
+       // when doing getElementsByTagName("*")
+
+       // Create a fake element
+       var div = document.createElement("div");
+       div.appendChild( document.createComment("") );
+
+       // Make sure no comments are found
+       if ( div.getElementsByTagName("*").length > 0 ) {
+               Expr.find.TAG = function( match, context ) {
+                       var results = context.getElementsByTagName( match[1] );
+
+                       // Filter out possible comments
+                       if ( match[1] === "*" ) {
+                               var tmp = [];
+
+                               for ( var i = 0; results[i]; i++ ) {
+                                       if ( results[i].nodeType === 1 ) {
+                                               tmp.push( results[i] );
+                                       }
+                               }
+
+                               results = tmp;
+                       }
+
+                       return results;
+               };
+       }
+
+       // Check to see if an attribute returns normalized href attributes
+       div.innerHTML = "<a href='#'></a>";
+
+       if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
+                       div.firstChild.getAttribute("href") !== "#" ) {
+
+               Expr.attrHandle.href = function( elem ) {
+                       return elem.getAttribute( "href", 2 );
+               };
+       }
+
+       // release memory in IE
+       div = null;
+})();
+
+if ( document.querySelectorAll ) {
+       (function(){
+               var oldSizzle = Sizzle,
+                       div = document.createElement("div"),
+                       id = "__sizzle__";
+
+               div.innerHTML = "<p class='TEST'></p>";
+
+               // Safari can't handle uppercase or unicode characters when
+               // in quirks mode.
+               if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
+                       return;
+               }
+       
+               Sizzle = function( query, context, extra, seed ) {
+                       context = context || document;
+
+                       // Only use querySelectorAll on non-XML documents
+                       // (ID selectors don't work in non-HTML documents)
+                       if ( !seed && !Sizzle.isXML(context) ) {
+                               // See if we find a selector to speed up
+                               var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
+                               
+                               if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
+                                       // Speed-up: Sizzle("TAG")
+                                       if ( match[1] ) {
+                                               return makeArray( context.getElementsByTagName( query ), extra );
+                                       
+                                       // Speed-up: Sizzle(".CLASS")
+                                       } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
+                                               return makeArray( context.getElementsByClassName( match[2] ), extra );
+                                       }
+                               }
+                               
+                               if ( context.nodeType === 9 ) {
+                                       // Speed-up: Sizzle("body")
+                                       // The body element only exists once, optimize finding it
+                                       if ( query === "body" && context.body ) {
+                                               return makeArray( [ context.body ], extra );
+                                               
+                                       // Speed-up: Sizzle("#ID")
+                                       } else if ( match && match[3] ) {
+                                               var elem = context.getElementById( match[3] );
+
+                                               // Check parentNode to catch when Blackberry 4.6 returns
+                                               // nodes that are no longer in the document #6963
+                                               if ( elem && elem.parentNode ) {
+                                                       // Handle the case where IE and Opera return items
+                                                       // by name instead of ID
+                                                       if ( elem.id === match[3] ) {
+                                                               return makeArray( [ elem ], extra );
+                                                       }
+                                                       
+                                               } else {
+                                                       return makeArray( [], extra );
+                                               }
+                                       }
+                                       
+                                       try {
+                                               return makeArray( context.querySelectorAll(query), extra );
+                                       } catch(qsaError) {}
+
+                               // qSA works strangely on Element-rooted queries
+                               // We can work around this by specifying an extra ID on the root
+                               // and working up from there (Thanks to Andrew Dupont for the technique)
+                               // IE 8 doesn't work on object elements
+                               } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+                                       var oldContext = context,
+                                               old = context.getAttribute( "id" ),
+                                               nid = old || id,
+                                               hasParent = context.parentNode,
+                                               relativeHierarchySelector = /^\s*[+~]/.test( query );
+
+                                       if ( !old ) {
+                                               context.setAttribute( "id", nid );
+                                       } else {
+                                               nid = nid.replace( /'/g, "\\$&" );
+                                       }
+                                       if ( relativeHierarchySelector && hasParent ) {
+                                               context = context.parentNode;
+                                       }
+
+                                       try {
+                                               if ( !relativeHierarchySelector || hasParent ) {
+                                                       return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
+                                               }
+
+                                       } catch(pseudoError) {
+                                       } finally {
+                                               if ( !old ) {
+                                                       oldContext.removeAttribute( "id" );
+                                               }
+                                       }
+                               }
+                       }
+               
+                       return oldSizzle(query, context, extra, seed);
+               };
+
+               for ( var prop in oldSizzle ) {
+                       Sizzle[ prop ] = oldSizzle[ prop ];
+               }
+
+               // release memory in IE
+               div = null;
+       })();
+}
+
+(function(){
+       var html = document.documentElement,
+               matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
+
+       if ( matches ) {
+               // Check to see if it's possible to do matchesSelector
+               // on a disconnected node (IE 9 fails this)
+               var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
+                       pseudoWorks = false;
+
+               try {
+                       // This should fail with an exception
+                       // Gecko does not error, returns false instead
+                       matches.call( document.documentElement, "[test!='']:sizzle" );
+       
+               } catch( pseudoError ) {
+                       pseudoWorks = true;
+               }
+
+               Sizzle.matchesSelector = function( node, expr ) {
+                       // Make sure that attribute selectors are quoted
+                       expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
+
+                       if ( !Sizzle.isXML( node ) ) {
+                               try { 
+                                       if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
+                                               var ret = matches.call( node, expr );
+
+                                               // IE 9's matchesSelector returns false on disconnected nodes
+                                               if ( ret || !disconnectedMatch ||
+                                                               // As well, disconnected nodes are said to be in a document
+                                                               // fragment in IE 9, so check for that
+                                                               node.document && node.document.nodeType !== 11 ) {
+                                                       return ret;
+                                               }
+                                       }
+                               } catch(e) {}
+                       }
+
+                       return Sizzle(expr, null, null, [node]).length > 0;
+               };
+       }
+})();
+
+(function(){
+       var div = document.createElement("div");
+
+       div.innerHTML = "<div class='test e'></div><div class='test'></div>";
+
+       // Opera can't find a second classname (in 9.6)
+       // Also, make sure that getElementsByClassName actually exists
+       if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
+               return;
+       }
+
+       // Safari caches class attributes, doesn't catch changes (in 3.2)
+       div.lastChild.className = "e";
+
+       if ( div.getElementsByClassName("e").length === 1 ) {
+               return;
+       }
+       
+       Expr.order.splice(1, 0, "CLASS");
+       Expr.find.CLASS = function( match, context, isXML ) {
+               if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
+                       return context.getElementsByClassName(match[1]);
+               }
+       };
+
+       // release memory in IE
+       div = null;
+})();
+
+function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+
+               if ( elem ) {
+                       var match = false;
+
+                       elem = elem[dir];
+
+                       while ( elem ) {
+                               if ( elem[ expando ] === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+
+                               if ( elem.nodeType === 1 && !isXML ){
+                                       elem[ expando ] = doneName;
+                                       elem.sizset = i;
+                               }
+
+                               if ( elem.nodeName.toLowerCase() === cur ) {
+                                       match = elem;
+                                       break;
+                               }
+
+                               elem = elem[dir];
+                       }
+
+                       checkSet[i] = match;
+               }
+       }
+}
+
+function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
+       for ( var i = 0, l = checkSet.length; i < l; i++ ) {
+               var elem = checkSet[i];
+
+               if ( elem ) {
+                       var match = false;
+                       
+                       elem = elem[dir];
+
+                       while ( elem ) {
+                               if ( elem[ expando ] === doneName ) {
+                                       match = checkSet[elem.sizset];
+                                       break;
+                               }
+
+                               if ( elem.nodeType === 1 ) {
+                                       if ( !isXML ) {
+                                               elem[ expando ] = doneName;
+                                               elem.sizset = i;
+                                       }
+
+                                       if ( typeof cur !== "string" ) {
+                                               if ( elem === cur ) {
+                                                       match = true;
+                                                       break;
+                                               }
+
+                                       } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
+                                               match = elem;
+                                               break;
+                                       }
+                               }
+
+                               elem = elem[dir];
+                       }
+
+                       checkSet[i] = match;
+               }
+       }
+}
+
+if ( document.documentElement.contains ) {
+       Sizzle.contains = function( a, b ) {
+               return a !== b && (a.contains ? a.contains(b) : true);
+       };
+
+} else if ( document.documentElement.compareDocumentPosition ) {
+       Sizzle.contains = function( a, b ) {
+               return !!(a.compareDocumentPosition(b) & 16);
+       };
+
+} else {
+       Sizzle.contains = function() {
+               return false;
+       };
+}
+
+Sizzle.isXML = function( elem ) {
+       // documentElement is verified for cases where it doesn't yet exist
+       // (such as loading iframes in IE - #4833) 
+       var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
+
+       return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+var posProcess = function( selector, context, seed ) {
+       var match,
+               tmpSet = [],
+               later = "",
+               root = context.nodeType ? [context] : context;
+
+       // Position selectors must be done after the filter
+       // And so must :not(positional) so we move all PSEUDOs to the end
+       while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
+               later += match[0];
+               selector = selector.replace( Expr.match.PSEUDO, "" );
+       }
+
+       selector = Expr.relative[selector] ? selector + "*" : selector;
+
+       for ( var i = 0, l = root.length; i < l; i++ ) {
+               Sizzle( selector, root[i], tmpSet, seed );
+       }
+
+       return Sizzle.filter( later, tmpSet );
+};
+
+// EXPOSE
+// Override sizzle attribute retrieval
+Sizzle.attr = jQuery.attr;
+Sizzle.selectors.attrMap = {};
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.filters;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})();
+
+
+var runtil = /Until$/,
+       rparentsprev = /^(?:parents|prevUntil|prevAll)/,
+       // Note: This RegExp should be improved, or likely pulled from Sizzle
+       rmultiselector = /,/,
+       isSimple = /^.[^:#\[\.,]*$/,
+       slice = Array.prototype.slice,
+       POS = jQuery.expr.match.POS,
+       // methods guaranteed to produce a unique set when starting from a unique set
+       guaranteedUnique = {
+               children: true,
+               contents: true,
+               next: true,
+               prev: true
+       };
+
+jQuery.fn.extend({
+       find: function( selector ) {
+               var self = this,
+                       i, l;
+
+               if ( typeof selector !== "string" ) {
+                       return jQuery( selector ).filter(function() {
+                               for ( i = 0, l = self.length; i < l; i++ ) {
+                                       if ( jQuery.contains( self[ i ], this ) ) {
+                                               return true;
+                                       }
+                               }
+                       });
+               }
+
+               var ret = this.pushStack( "", "find", selector ),
+                       length, n, r;
+
+               for ( i = 0, l = this.length; i < l; i++ ) {
+                       length = ret.length;
+                       jQuery.find( selector, this[i], ret );
+
+                       if ( i > 0 ) {
+                               // Make sure that the results are unique
+                               for ( n = length; n < ret.length; n++ ) {
+                                       for ( r = 0; r < length; r++ ) {
+                                               if ( ret[r] === ret[n] ) {
+                                                       ret.splice(n--, 1);
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return ret;
+       },
+
+       has: function( target ) {
+               var targets = jQuery( target );
+               return this.filter(function() {
+                       for ( var i = 0, l = targets.length; i < l; i++ ) {
+                               if ( jQuery.contains( this, targets[i] ) ) {
+                                       return true;
+                               }
+                       }
+               });
+       },
+
+       not: function( selector ) {
+               return this.pushStack( winnow(this, selector, false), "not", selector);
+       },
+
+       filter: function( selector ) {
+               return this.pushStack( winnow(this, selector, true), "filter", selector );
+       },
+
+       is: function( selector ) {
+               return !!selector && ( 
+                       typeof selector === "string" ?
+                               // If this is a positional selector, check membership in the returned set
+                               // so $("p:first").is("p:last") won't return true for a doc with two "p".
+                               POS.test( selector ) ? 
+                                       jQuery( selector, this.context ).index( this[0] ) >= 0 :
+                                       jQuery.filter( selector, this ).length > 0 :
+                               this.filter( selector ).length > 0 );
+       },
+
+       closest: function( selectors, context ) {
+               var ret = [], i, l, cur = this[0];
+               
+               // Array (deprecated as of jQuery 1.7)
+               if ( jQuery.isArray( selectors ) ) {
+                       var level = 1;
+
+                       while ( cur && cur.ownerDocument && cur !== context ) {
+                               for ( i = 0; i < selectors.length; i++ ) {
+
+                                       if ( jQuery( cur ).is( selectors[ i ] ) ) {
+                                               ret.push({ selector: selectors[ i ], elem: cur, level: level });
+                                       }
+                               }
+
+                               cur = cur.parentNode;
+                               level++;
+                       }
+
+                       return ret;
+               }
+
+               // String
+               var pos = POS.test( selectors ) || typeof selectors !== "string" ?
+                               jQuery( selectors, context || this.context ) :
+                               0;
+
+               for ( i = 0, l = this.length; i < l; i++ ) {
+                       cur = this[i];
+
+                       while ( cur ) {
+                               if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
+                                       ret.push( cur );
+                                       break;
+
+                               } else {
+                                       cur = cur.parentNode;
+                                       if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
+
+               return this.pushStack( ret, "closest", selectors );
+       },
+
+       // Determine the position of an element within
+       // the matched set of elements
+       index: function( elem ) {
+
+               // No argument, return index in parent
+               if ( !elem ) {
+                       return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
+               }
+
+               // index in selector
+               if ( typeof elem === "string" ) {
+                       return jQuery.inArray( this[0], jQuery( elem ) );
+               }
+
+               // Locate the position of the desired element
+               return jQuery.inArray(
+                       // If it receives a jQuery object, the first element is used
+                       elem.jquery ? elem[0] : elem, this );
+       },
+
+       add: function( selector, context ) {
+               var set = typeof selector === "string" ?
+                               jQuery( selector, context ) :
+                               jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+                       all = jQuery.merge( this.get(), set );
+
+               return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
+                       all :
+                       jQuery.unique( all ) );
+       },
+
+       andSelf: function() {
+               return this.add( this.prevObject );
+       }
+});
+
+// A painfully simple check to see if an element is disconnected
+// from a document (should be improved, where feasible).
+function isDisconnected( node ) {
+       return !node || !node.parentNode || node.parentNode.nodeType === 11;
+}
+
+jQuery.each({
+       parent: function( elem ) {
+               var parent = elem.parentNode;
+               return parent && parent.nodeType !== 11 ? parent : null;
+       },
+       parents: function( elem ) {
+               return jQuery.dir( elem, "parentNode" );
+       },
+       parentsUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "parentNode", until );
+       },
+       next: function( elem ) {
+               return jQuery.nth( elem, 2, "nextSibling" );
+       },
+       prev: function( elem ) {
+               return jQuery.nth( elem, 2, "previousSibling" );
+       },
+       nextAll: function( elem ) {
+               return jQuery.dir( elem, "nextSibling" );
+       },
+       prevAll: function( elem ) {
+               return jQuery.dir( elem, "previousSibling" );
+       },
+       nextUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "nextSibling", until );
+       },
+       prevUntil: function( elem, i, until ) {
+               return jQuery.dir( elem, "previousSibling", until );
+       },
+       siblings: function( elem ) {
+               return jQuery.sibling( elem.parentNode.firstChild, elem );
+       },
+       children: function( elem ) {
+               return jQuery.sibling( elem.firstChild );
+       },
+       contents: function( elem ) {
+               return jQuery.nodeName( elem, "iframe" ) ?
+                       elem.contentDocument || elem.contentWindow.document :
+                       jQuery.makeArray( elem.childNodes );
+       }
+}, function( name, fn ) {
+       jQuery.fn[ name ] = function( until, selector ) {
+               var ret = jQuery.map( this, fn, until );
+
+               if ( !runtil.test( name ) ) {
+                       selector = until;
+               }
+
+               if ( selector && typeof selector === "string" ) {
+                       ret = jQuery.filter( selector, ret );
+               }
+
+               ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
+
+               if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
+                       ret = ret.reverse();
+               }
+
+               return this.pushStack( ret, name, slice.call( arguments ).join(",") );
+       };
+});
+
+jQuery.extend({
+       filter: function( expr, elems, not ) {
+               if ( not ) {
+                       expr = ":not(" + expr + ")";
+               }
+
+               return elems.length === 1 ?
+                       jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
+                       jQuery.find.matches(expr, elems);
+       },
+
+       dir: function( elem, dir, until ) {
+               var matched = [],
+                       cur = elem[ dir ];
+
+               while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+                       if ( cur.nodeType === 1 ) {
+                               matched.push( cur );
+                       }
+                       cur = cur[dir];
+               }
+               return matched;
+       },
+
+       nth: function( cur, result, dir, elem ) {
+               result = result || 1;
+               var num = 0;
+
+               for ( ; cur; cur = cur[dir] ) {
+                       if ( cur.nodeType === 1 && ++num === result ) {
+                               break;
+                       }
+               }
+
+               return cur;
+       },
+
+       sibling: function( n, elem ) {
+               var r = [];
+
+               for ( ; n; n = n.nextSibling ) {
+                       if ( n.nodeType === 1 && n !== elem ) {
+                               r.push( n );
+                       }
+               }
+
+               return r;
+       }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, keep ) {
+
+       // Can't pass null or undefined to indexOf in Firefox 4
+       // Set to 0 to skip string check
+       qualifier = qualifier || 0;
+
+       if ( jQuery.isFunction( qualifier ) ) {
+               return jQuery.grep(elements, function( elem, i ) {
+                       var retVal = !!qualifier.call( elem, i, elem );
+                       return retVal === keep;
+               });
+
+       } else if ( qualifier.nodeType ) {
+               return jQuery.grep(elements, function( elem, i ) {
+                       return ( elem === qualifier ) === keep;
+               });
+
+       } else if ( typeof qualifier === "string" ) {
+               var filtered = jQuery.grep(elements, function( elem ) {
+                       return elem.nodeType === 1;
+               });
+
+               if ( isSimple.test( qualifier ) ) {
+                       return jQuery.filter(qualifier, filtered, !keep);
+               } else {
+                       qualifier = jQuery.filter( qualifier, filtered );
+               }
+       }
+
+       return jQuery.grep(elements, function( elem, i ) {
+               return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
+       });
+}
+
+
+
+
+function createSafeFragment( document ) {
+       var list = nodeNames.split( "|" ),
+       safeFrag = document.createDocumentFragment();
+
+       if ( safeFrag.createElement ) {
+               while ( list.length ) {
+                       safeFrag.createElement(
+                               list.pop()
+                       );
+               }
+       }
+       return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
+               "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+       rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
+       rleadingWhitespace = /^\s+/,
+       rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
+       rtagName = /<([\w:]+)/,
+       rtbody = /<tbody/i,
+       rhtml = /<|&#?\w+;/,
+       rnoInnerhtml = /<(?:script|style)/i,
+       rnocache = /<(?:script|object|embed|option|style)/i,
+       rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
+       // checked="checked" or checked
+       rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+       rscriptType = /\/(java|ecma)script/i,
+       rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
+       wrapMap = {
+               option: [ 1, "<select multiple='multiple'>", "</select>" ],
+               legend: [ 1, "<fieldset>", "</fieldset>" ],
+               thead: [ 1, "<table>", "</table>" ],
+               tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+               td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+               col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+               area: [ 1, "<map>", "</map>" ],
+               _default: [ 0, "", "" ]
+       },
+       safeFragment = createSafeFragment( document );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+// IE can't serialize <link> and <script> tags normally
+if ( !jQuery.support.htmlSerialize ) {
+       wrapMap._default = [ 1, "div<div>", "</div>" ];
+}
+
+jQuery.fn.extend({
+       text: function( text ) {
+               if ( jQuery.isFunction(text) ) {
+                       return this.each(function(i) {
+                               var self = jQuery( this );
+
+                               self.text( text.call(this, i, self.text()) );
+                       });
+               }
+
+               if ( typeof text !== "object" && text !== undefined ) {
+                       return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
+               }
+
+               return jQuery.text( this );
+       },
+
+       wrapAll: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapAll( html.call(this, i) );
+                       });
+               }
+
+               if ( this[0] ) {
+                       // The elements to wrap the target around
+                       var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+                       if ( this[0].parentNode ) {
+                               wrap.insertBefore( this[0] );
+                       }
+
+                       wrap.map(function() {
+                               var elem = this;
+
+                               while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+                                       elem = elem.firstChild;
+                               }
+
+                               return elem;
+                       }).append( this );
+               }
+
+               return this;
+       },
+
+       wrapInner: function( html ) {
+               if ( jQuery.isFunction( html ) ) {
+                       return this.each(function(i) {
+                               jQuery(this).wrapInner( html.call(this, i) );
+                       });
+               }
+
+               return this.each(function() {
+                       var self = jQuery( this ),
+                               contents = self.contents();
+
+                       if ( contents.length ) {
+                               contents.wrapAll( html );
+
+                       } else {
+                               self.append( html );
+                       }
+               });
+       },
+
+       wrap: function( html ) {
+               var isFunction = jQuery.isFunction( html );
+
+               return this.each(function(i) {
+                       jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+               });
+       },
+
+       unwrap: function() {
+               return this.parent().each(function() {
+                       if ( !jQuery.nodeName( this, "body" ) ) {
+                               jQuery( this ).replaceWith( this.childNodes );
+                       }
+               }).end();
+       },
+
+       append: function() {
+               return this.domManip(arguments, true, function( elem ) {
+                       if ( this.nodeType === 1 ) {
+                               this.appendChild( elem );
+                       }
+               });
+       },
+
+       prepend: function() {
+               return this.domManip(arguments, true, function( elem ) {
+                       if ( this.nodeType === 1 ) {
+                               this.insertBefore( elem, this.firstChild );
+                       }
+               });
+       },
+
+       before: function() {
+               if ( this[0] && this[0].parentNode ) {
+                       return this.domManip(arguments, false, function( elem ) {
+                               this.parentNode.insertBefore( elem, this );
+                       });
+               } else if ( arguments.length ) {
+                       var set = jQuery.clean( arguments );
+                       set.push.apply( set, this.toArray() );
+                       return this.pushStack( set, "before", arguments );
+               }
+       },
+
+       after: function() {
+               if ( this[0] && this[0].parentNode ) {
+                       return this.domManip(arguments, false, function( elem ) {
+                               this.parentNode.insertBefore( elem, this.nextSibling );
+                       });
+               } else if ( arguments.length ) {
+                       var set = this.pushStack( this, "after", arguments );
+                       set.push.apply( set, jQuery.clean(arguments) );
+                       return set;
+               }
+       },
+
+       // keepData is for internal use only--do not document
+       remove: function( selector, keepData ) {
+               for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+                       if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
+                               if ( !keepData && elem.nodeType === 1 ) {
+                                       jQuery.cleanData( elem.getElementsByTagName("*") );
+                                       jQuery.cleanData( [ elem ] );
+                               }
+
+                               if ( elem.parentNode ) {
+                                       elem.parentNode.removeChild( elem );
+                               }
+                       }
+               }
+
+               return this;
+       },
+
+       empty: function() {
+               for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
+                       // Remove element nodes and prevent memory leaks
+                       if ( elem.nodeType === 1 ) {
+                               jQuery.cleanData( elem.getElementsByTagName("*") );
+                       }
+
+                       // Remove any remaining nodes
+                       while ( elem.firstChild ) {
+                               elem.removeChild( elem.firstChild );
+                       }
+               }
+
+               return this;
+       },
+
+       clone: function( dataAndEvents, deepDataAndEvents ) {
+               dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+               deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+               return this.map( function () {
+                       return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+               });
+       },
+
+       html: function( value ) {
+               if ( value === undefined ) {
+                       return this[0] && this[0].nodeType === 1 ?
+                               this[0].innerHTML.replace(rinlinejQuery, "") :
+                               null;
+
+               // See if we can take a shortcut and just use innerHTML
+               } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+                       (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
+                       !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
+
+                       value = value.replace(rxhtmlTag, "<$1></$2>");
+
+                       try {
+                               for ( var i = 0, l = this.length; i < l; i++ ) {
+                                       // Remove element nodes and prevent memory leaks
+                                       if ( this[i].nodeType === 1 ) {
+                                               jQuery.cleanData( this[i].getElementsByTagName("*") );
+                                               this[i].innerHTML = value;
+                                       }
+                               }
+
+                       // If using innerHTML throws an exception, use the fallback method
+                       } catch(e) {
+                               this.empty().append( value );
+                       }
+
+               } else if ( jQuery.isFunction( value ) ) {
+                       this.each(function(i){
+                               var self = jQuery( this );
+
+                               self.html( value.call(this, i, self.html()) );
+                       });
+
+               } else {
+                       this.empty().append( value );
+               }
+
+               return this;
+       },
+
+       replaceWith: function( value ) {
+               if ( this[0] && this[0].parentNode ) {
+                       // Make sure that the elements are removed from the DOM before they are inserted
+                       // this can help fix replacing a parent with child elements
+                       if ( jQuery.isFunction( value ) ) {
+                               return this.each(function(i) {
+                                       var self = jQuery(this), old = self.html();
+                                       self.replaceWith( value.call( this, i, old ) );
+                               });
+                       }
+
+                       if ( typeof value !== "string" ) {
+                               value = jQuery( value ).detach();
+                       }
+
+                       return this.each(function() {
+                               var next = this.nextSibling,
+                                       parent = this.parentNode;
+
+                               jQuery( this ).remove();
+
+                               if ( next ) {
+                                       jQuery(next).before( value );
+                               } else {
+                                       jQuery(parent).append( value );
+                               }
+                       });
+               } else {
+                       return this.length ?
+                               this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
+                               this;
+               }
+       },
+
+       detach: function( selector ) {
+               return this.remove( selector, true );
+       },
+
+       domManip: function( args, table, callback ) {
+               var results, first, fragment, parent,
+                       value = args[0],
+                       scripts = [];
+
+               // We can't cloneNode fragments that contain checked, in WebKit
+               if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
+                       return this.each(function() {
+                               jQuery(this).domManip( args, table, callback, true );
+                       });
+               }
+
+               if ( jQuery.isFunction(value) ) {
+                       return this.each(function(i) {
+                               var self = jQuery(this);
+                               args[0] = value.call(this, i, table ? self.html() : undefined);
+                               self.domManip( args, table, callback );
+                       });
+               }
+
+               if ( this[0] ) {
+                       parent = value && value.parentNode;
+
+                       // If we're in a fragment, just use that instead of building a new one
+                       if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
+                               results = { fragment: parent };
+
+                       } else {
+                               results = jQuery.buildFragment( args, this, scripts );
+                       }
+
+                       fragment = results.fragment;
+
+                       if ( fragment.childNodes.length === 1 ) {
+                               first = fragment = fragment.firstChild;
+                       } else {
+                               first = fragment.firstChild;
+                       }
+
+                       if ( first ) {
+                               table = table && jQuery.nodeName( first, "tr" );
+
+                               for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
+                                       callback.call(
+                                               table ?
+                                                       root(this[i], first) :
+                                                       this[i],
+                                               // Make sure that we do not leak memory by inadvertently discarding
+                                               // the original fragment (which might have attached data) instead of
+                                               // using it; in addition, use the original fragment object for the last
+                                               // item instead of first because it can end up being emptied incorrectly
+                                               // in certain situations (Bug #8070).
+                                               // Fragments from the fragment cache must always be cloned and never used
+                                               // in place.
+                                               results.cacheable || ( l > 1 && i < lastIndex ) ?
+                                                       jQuery.clone( fragment, true, true ) :
+                                                       fragment
+                                       );
+                               }
+                       }
+
+                       if ( scripts.length ) {
+                               jQuery.each( scripts, evalScript );
+                       }
+               }
+
+               return this;
+       }
+});
+
+function root( elem, cur ) {
+       return jQuery.nodeName(elem, "table") ?
+               (elem.getElementsByTagName("tbody")[0] ||
+               elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
+               elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+
+       if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+               return;
+       }
+
+       var type, i, l,
+               oldData = jQuery._data( src ),
+               curData = jQuery._data( dest, oldData ),
+               events = oldData.events;
+
+       if ( events ) {
+               delete curData.handle;
+               curData.events = {};
+
+               for ( type in events ) {
+                       for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+                               jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
+                       }
+               }
+       }
+
+       // make the cloned public data object a copy from the original
+       if ( curData.data ) {
+               curData.data = jQuery.extend( {}, curData.data );
+       }
+}
+
+function cloneFixAttributes( src, dest ) {
+       var nodeName;
+
+       // We do not need to do anything for non-Elements
+       if ( dest.nodeType !== 1 ) {
+               return;
+       }
+
+       // clearAttributes removes the attributes, which we don't want,
+       // but also removes the attachEvent events, which we *do* want
+       if ( dest.clearAttributes ) {
+               dest.clearAttributes();
+       }
+
+       // mergeAttributes, in contrast, only merges back on the
+       // original attributes, not the events
+       if ( dest.mergeAttributes ) {
+               dest.mergeAttributes( src );
+       }
+
+       nodeName = dest.nodeName.toLowerCase();
+
+       // IE6-8 fail to clone children inside object elements that use
+       // the proprietary classid attribute value (rather than the type
+       // attribute) to identify the type of content to display
+       if ( nodeName === "object" ) {
+               dest.outerHTML = src.outerHTML;
+
+       } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+               // IE6-8 fails to persist the checked state of a cloned checkbox
+               // or radio button. Worse, IE6-7 fail to give the cloned element
+               // a checked appearance if the defaultChecked value isn't also set
+               if ( src.checked ) {
+                       dest.defaultChecked = dest.checked = src.checked;
+               }
+
+               // IE6-7 get confused and end up setting the value of a cloned
+               // checkbox/radio button to an empty string instead of "on"
+               if ( dest.value !== src.value ) {
+                       dest.value = src.value;
+               }
+
+       // IE6-8 fails to return the selected option to the default selected
+       // state when cloning options
+       } else if ( nodeName === "option" ) {
+               dest.selected = src.defaultSelected;
+
+       // IE6-8 fails to set the defaultValue to the correct value when
+       // cloning other types of input fields
+       } else if ( nodeName === "input" || nodeName === "textarea" ) {
+               dest.defaultValue = src.defaultValue;
+       }
+
+       // Event data gets referenced instead of copied if the expando
+       // gets copied too
+       dest.removeAttribute( jQuery.expando );
+}
+
+jQuery.buildFragment = function( args, nodes, scripts ) {
+       var fragment, cacheable, cacheresults, doc,
+       first = args[ 0 ];
+
+       // nodes may contain either an explicit document object,
+       // a jQuery collection or context object.
+       // If nodes[0] contains a valid object to assign to doc
+       if ( nodes && nodes[0] ) {
+               doc = nodes[0].ownerDocument || nodes[0];
+       }
+
+       // Ensure that an attr object doesn't incorrectly stand in as a document object
+       // Chrome and Firefox seem to allow this to occur and will throw exception
+       // Fixes #8950
+       if ( !doc.createDocumentFragment ) {
+               doc = document;
+       }
+
+       // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
+       // Cloning options loses the selected state, so don't cache them
+       // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
+       // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
+       // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
+       if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
+               first.charAt(0) === "<" && !rnocache.test( first ) &&
+               (jQuery.support.checkClone || !rchecked.test( first )) &&
+               (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {
+
+               cacheable = true;
+
+               cacheresults = jQuery.fragments[ first ];
+               if ( cacheresults && cacheresults !== 1 ) {
+                       fragment = cacheresults;
+               }
+       }
+
+       if ( !fragment ) {
+               fragment = doc.createDocumentFragment();
+               jQuery.clean( args, doc, fragment, scripts );
+       }
+
+       if ( cacheable ) {
+               jQuery.fragments[ first ] = cacheresults ? fragment : 1;
+       }
+
+       return { fragment: fragment, cacheable: cacheable };
+};
+
+jQuery.fragments = {};
+
+jQuery.each({
+       appendTo: "append",
+       prependTo: "prepend",
+       insertBefore: "before",
+       insertAfter: "after",
+       replaceAll: "replaceWith"
+}, function( name, original ) {
+       jQuery.fn[ name ] = function( selector ) {
+               var ret = [],
+                       insert = jQuery( selector ),
+                       parent = this.length === 1 && this[0].parentNode;
+
+               if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
+                       insert[ original ]( this[0] );
+                       return this;
+
+               } else {
+                       for ( var i = 0, l = insert.length; i < l; i++ ) {
+                               var elems = ( i > 0 ? this.clone(true) : this ).get();
+                               jQuery( insert[i] )[ original ]( elems );
+                               ret = ret.concat( elems );
+                       }
+
+                       return this.pushStack( ret, name, insert.selector );
+               }
+       };
+});
+
+function getAll( elem ) {
+       if ( typeof elem.getElementsByTagName !== "undefined" ) {
+               return elem.getElementsByTagName( "*" );
+
+       } else if ( typeof elem.querySelectorAll !== "undefined" ) {
+               return elem.querySelectorAll( "*" );
+
+       } else {
+               return [];
+       }
+}
+
+// Used in clean, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+       if ( elem.type === "checkbox" || elem.type === "radio" ) {
+               elem.defaultChecked = elem.checked;
+       }
+}
+// Finds all inputs and passes them to fixDefaultChecked
+function findInputs( elem ) {
+       var nodeName = ( elem.nodeName || "" ).toLowerCase();
+       if ( nodeName === "input" ) {
+               fixDefaultChecked( elem );
+       // Skip scripts, get other children
+       } else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
+               jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
+       }
+}
+
+// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
+function shimCloneNode( elem ) {
+       var div = document.createElement( "div" );
+       safeFragment.appendChild( div );
+
+       div.innerHTML = elem.outerHTML;
+       return div.firstChild;
+}
+
+jQuery.extend({
+       clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+               var srcElements,
+                       destElements,
+                       i,
+                       // IE<=8 does not properly clone detached, unknown element nodes
+                       clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
+                               elem.cloneNode( true ) :
+                               shimCloneNode( elem );
+
+               if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
+                               (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+                       // IE copies events bound via attachEvent when using cloneNode.
+                       // Calling detachEvent on the clone will also remove the events
+                       // from the original. In order to get around this, we use some
+                       // proprietary methods to clear the events. Thanks to MooTools
+                       // guys for this hotness.
+
+                       cloneFixAttributes( elem, clone );
+
+                       // Using Sizzle here is crazy slow, so we use getElementsByTagName instead
+                       srcElements = getAll( elem );
+                       destElements = getAll( clone );
+
+                       // Weird iteration because IE will replace the length property
+                       // with an element if you are cloning the body and one of the
+                       // elements on the page has a name or id of "length"
+                       for ( i = 0; srcElements[i]; ++i ) {
+                               // Ensure that the destination node is not null; Fixes #9587
+                               if ( destElements[i] ) {
+                                       cloneFixAttributes( srcElements[i], destElements[i] );
+                               }
+                       }
+               }
+
+               // Copy the events from the original to the clone
+               if ( dataAndEvents ) {
+                       cloneCopyEvent( elem, clone );
+
+                       if ( deepDataAndEvents ) {
+                               srcElements = getAll( elem );
+                               destElements = getAll( clone );
+
+                               for ( i = 0; srcElements[i]; ++i ) {
+                                       cloneCopyEvent( srcElements[i], destElements[i] );
+                               }
+                       }
+               }
+
+               srcElements = destElements = null;
+
+               // Return the cloned set
+               return clone;
+       },
+
+       clean: function( elems, context, fragment, scripts ) {
+               var checkScriptType;
+
+               context = context || document;
+
+               // !context.createElement fails in IE with an error but returns typeof 'object'
+               if ( typeof context.createElement === "undefined" ) {
+                       context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
+               }
+
+               var ret = [], j;
+
+               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+                       if ( typeof elem === "number" ) {
+                               elem += "";
+                       }
+
+                       if ( !elem ) {
+                               continue;
+                       }
+
+                       // Convert html string into DOM nodes
+                       if ( typeof elem === "string" ) {
+                               if ( !rhtml.test( elem ) ) {
+                                       elem = context.createTextNode( elem );
+                               } else {
+                                       // Fix "XHTML"-style tags in all browsers
+                                       elem = elem.replace(rxhtmlTag, "<$1></$2>");
+
+                                       // Trim whitespace, otherwise indexOf won't work as expected
+                                       var tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(),
+                                               wrap = wrapMap[ tag ] || wrapMap._default,
+                                               depth = wrap[0],
+                                               div = context.createElement("div");
+
+                                       // Append wrapper element to unknown element safe doc fragment
+                                       if ( context === document ) {
+                                               // Use the fragment we've already created for this document
+                                               safeFragment.appendChild( div );
+                                       } else {
+                                               // Use a fragment created with the owner document
+                                               createSafeFragment( context ).appendChild( div );
+                                       }
+
+                                       // Go to html and back, then peel off extra wrappers
+                                       div.innerHTML = wrap[1] + elem + wrap[2];
+
+                                       // Move to the right depth
+                                       while ( depth-- ) {
+                                               div = div.lastChild;
+                                       }
+
+                                       // Remove IE's autoinserted <tbody> from table fragments
+                                       if ( !jQuery.support.tbody ) {
+
+                                               // String was a <table>, *may* have spurious <tbody>
+                                               var hasBody = rtbody.test(elem),
+                                                       tbody = tag === "table" && !hasBody ?
+                                                               div.firstChild && div.firstChild.childNodes :
+
+                                                               // String was a bare <thead> or <tfoot>
+                                                               wrap[1] === "<table>" && !hasBody ?
+                                                                       div.childNodes :
+                                                                       [];
+
+                                               for ( j = tbody.length - 1; j >= 0 ; --j ) {
+                                                       if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
+                                                               tbody[ j ].parentNode.removeChild( tbody[ j ] );
+                                                       }
+                                               }
+                                       }
+
+                                       // IE completely kills leading whitespace when innerHTML is used
+                                       if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+                                               div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
+                                       }
+
+                                       elem = div.childNodes;
+                               }
+                       }
+
+                       // Resets defaultChecked for any radios and checkboxes
+                       // about to be appended to the DOM in IE 6/7 (#8060)
+                       var len;
+                       if ( !jQuery.support.appendChecked ) {
+                               if ( elem[0] && typeof (len = elem.length) === "number" ) {
+                                       for ( j = 0; j < len; j++ ) {
+                                               findInputs( elem[j] );
+                                       }
+                               } else {
+                                       findInputs( elem );
+                               }
+                       }
+
+                       if ( elem.nodeType ) {
+                               ret.push( elem );
+                       } else {
+                               ret = jQuery.merge( ret, elem );
+                       }
+               }
+
+               if ( fragment ) {
+                       checkScriptType = function( elem ) {
+                               return !elem.type || rscriptType.test( elem.type );
+                       };
+                       for ( i = 0; ret[i]; i++ ) {
+                               if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
+                                       scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
+
+                               } else {
+                                       if ( ret[i].nodeType === 1 ) {
+                                               var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
+
+                                               ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
+                                       }
+                                       fragment.appendChild( ret[i] );
+                               }
+                       }
+               }
+
+               return ret;
+       },
+
+       cleanData: function( elems ) {
+               var data, id,
+                       cache = jQuery.cache,
+                       special = jQuery.event.special,
+                       deleteExpando = jQuery.support.deleteExpando;
+
+               for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+                       if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
+                               continue;
+                       }
+
+                       id = elem[ jQuery.expando ];
+
+                       if ( id ) {
+                               data = cache[ id ];
+
+                               if ( data && data.events ) {
+                                       for ( var type in data.events ) {
+                                               if ( special[ type ] ) {
+                                                       jQuery.event.remove( elem, type );
+
+                                               // This is a shortcut to avoid jQuery.event.remove's overhead
+                                               } else {
+                                                       jQuery.removeEvent( elem, type, data.handle );
+                                               }
+                                       }
+
+                                       // Null the DOM reference to avoid IE6/7/8 leak (#7054)
+                                       if ( data.handle ) {
+                                               data.handle.elem = null;
+                                       }
+                               }
+
+                               if ( deleteExpando ) {
+                                       delete elem[ jQuery.expando ];
+
+                               } else if ( elem.removeAttribute ) {
+                                       elem.removeAttribute( jQuery.expando );
+                               }
+
+                               delete cache[ id ];
+                       }
+               }
+       }
+});
+
+function evalScript( i, elem ) {
+       if ( elem.src ) {
+               jQuery.ajax({
+                       url: elem.src,
+                       async: false,
+                       dataType: "script"
+               });
+       } else {
+               jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "/*$0*/" ) );
+       }
+
+       if ( elem.parentNode ) {
+               elem.parentNode.removeChild( elem );
+       }
+}
+
+
+
+
+var ralpha = /alpha\([^)]*\)/i,
+       ropacity = /opacity=([^)]*)/,
+       // fixed for IE9, see #8346
+       rupper = /([A-Z]|^ms)/g,
+       rnumpx = /^-?\d+(?:px)?$/i,
+       rnum = /^-?\d/,
+       rrelNum = /^([\-+])=([\-+.\de]+)/,
+
+       cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+       cssWidth = [ "Left", "Right" ],
+       cssHeight = [ "Top", "Bottom" ],
+       curCSS,
+
+       getComputedStyle,
+       currentStyle;
+
+jQuery.fn.css = function( name, value ) {
+       // Setting 'undefined' is a no-op
+       if ( arguments.length === 2 && value === undefined ) {
+               return this;
+       }
+
+       return jQuery.access( this, name, value, true, function( elem, name, value ) {
+               return value !== undefined ?
+                       jQuery.style( elem, name, value ) :
+                       jQuery.css( elem, name );
+       });
+};
+
+jQuery.extend({
+       // Add in style property hooks for overriding the default
+       // behavior of getting and setting a style property
+       cssHooks: {
+               opacity: {
+                       get: function( elem, computed ) {
+                               if ( computed ) {
+                                       // We should always get a number back from opacity
+                                       var ret = curCSS( elem, "opacity", "opacity" );
+                                       return ret === "" ? "1" : ret;
+
+                               } else {
+                                       return elem.style.opacity;
+                               }
+                       }
+               }
+       },
+
+       // Exclude the following css properties to add px
+       cssNumber: {
+               "fillOpacity": true,
+               "fontWeight": true,
+               "lineHeight": true,
+               "opacity": true,
+               "orphans": true,
+               "widows": true,
+               "zIndex": true,
+               "zoom": true
+       },
+
+       // Add in properties whose names you wish to fix before
+       // setting or getting the value
+       cssProps: {
+               // normalize float css property
+               "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
+       },
+
+       // Get and set the style property on a DOM Node
+       style: function( elem, name, value, extra ) {
+               // Don't set styles on text and comment nodes
+               if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+                       return;
+               }
+
+               // Make sure that we're working with the right name
+               var ret, type, origName = jQuery.camelCase( name ),
+                       style = elem.style, hooks = jQuery.cssHooks[ origName ];
+
+               name = jQuery.cssProps[ origName ] || origName;
+
+               // Check if we're setting a value
+               if ( value !== undefined ) {
+                       type = typeof value;
+
+                       // convert relative number strings (+= or -=) to relative numbers. #7345
+                       if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+                               value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
+                               // Fixes bug #9237
+                               type = "number";
+                       }
+
+                       // Make sure that NaN and null values aren't set. See: #7116
+                       if ( value == null || type === "number" && isNaN( value ) ) {
+                               return;
+                       }
+
+                       // If a number was passed in, add 'px' to the (except for certain CSS properties)
+                       if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+                               value += "px";
+                       }
+
+                       // If a hook was provided, use that value, otherwise just set the specified value
+                       if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
+                               // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
+                               // Fixes bug #5509
+                               try {
+                                       style[ name ] = value;
+                               } catch(e) {}
+                       }
+
+               } else {
+                       // If a hook was provided get the non-computed value from there
+                       if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+                               return ret;
+                       }
+
+                       // Otherwise just get the value from the style object
+                       return style[ name ];
+               }
+       },
+
+       css: function( elem, name, extra ) {
+               var ret, hooks;
+
+               // Make sure that we're working with the right name
+               name = jQuery.camelCase( name );
+               hooks = jQuery.cssHooks[ name ];
+               name = jQuery.cssProps[ name ] || name;
+
+               // cssFloat needs a special treatment
+               if ( name === "cssFloat" ) {
+                       name = "float";
+               }
+
+               // If a hook was provided get the computed value from there
+               if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
+                       return ret;
+
+               // Otherwise, if a way to get the computed value exists, use that
+               } else if ( curCSS ) {
+                       return curCSS( elem, name );
+               }
+       },
+
+       // A method for quickly swapping in/out CSS properties to get correct calculations
+       swap: function( elem, options, callback ) {
+               var old = {};
+
+               // Remember the old values, and insert the new ones
+               for ( var name in options ) {
+                       old[ name ] = elem.style[ name ];
+                       elem.style[ name ] = options[ name ];
+               }
+
+               callback.call( elem );
+
+               // Revert the old values
+               for ( name in options ) {
+                       elem.style[ name ] = old[ name ];
+               }
+       }
+});
+
+// DEPRECATED, Use jQuery.css() instead
+jQuery.curCSS = jQuery.css;
+
+jQuery.each(["height", "width"], function( i, name ) {
+       jQuery.cssHooks[ name ] = {
+               get: function( elem, computed, extra ) {
+                       var val;
+
+                       if ( computed ) {
+                               if ( elem.offsetWidth !== 0 ) {
+                                       return getWH( elem, name, extra );
+                               } else {
+                                       jQuery.swap( elem, cssShow, function() {
+                                               val = getWH( elem, name, extra );
+                                       });
+                               }
+
+                               return val;
+                       }
+               },
+
+               set: function( elem, value ) {
+                       if ( rnumpx.test( value ) ) {
+                               // ignore negative width and height values #1599
+                               value = parseFloat( value );
+
+                               if ( value >= 0 ) {
+                                       return value + "px";
+                               }
+
+                       } else {
+                               return value;
+                       }
+               }
+       };
+});
+
+if ( !jQuery.support.opacity ) {
+       jQuery.cssHooks.opacity = {
+               get: function( elem, computed ) {
+                       // IE uses filters for opacity
+                       return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+                               ( parseFloat( RegExp.$1 ) / 100 ) + "" :
+                               computed ? "1" : "";
+               },
+
+               set: function( elem, value ) {
+                       var style = elem.style,
+                               currentStyle = elem.currentStyle,
+                               opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+                               filter = currentStyle && currentStyle.filter || style.filter || "";
+
+                       // IE has trouble with opacity if it does not have layout
+                       // Force it by setting the zoom level
+                       style.zoom = 1;
+
+                       // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+                       if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
+
+                               // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+                               // if "filter:" is present at all, clearType is disabled, we want to avoid this
+                               // style.removeAttribute is IE Only, but so apparently is this code path...
+                               style.removeAttribute( "filter" );
+
+                               // if there there is no filter style applied in a css rule, we are done
+                               if ( currentStyle && !currentStyle.filter ) {
+                                       return;
+                               }
+                       }
+
+                       // otherwise, set new filter values
+                       style.filter = ralpha.test( filter ) ?
+                               filter.replace( ralpha, opacity ) :
+                               filter + " " + opacity;
+               }
+       };
+}
+
+jQuery(function() {
+       // This hook cannot be added until DOM ready because the support test
+       // for it is not run until after DOM ready
+       if ( !jQuery.support.reliableMarginRight ) {
+               jQuery.cssHooks.marginRight = {
+                       get: function( elem, computed ) {
+                               // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+                               // Work around by temporarily setting element display to inline-block
+                               var ret;
+                               jQuery.swap( elem, { "display": "inline-block" }, function() {
+                                       if ( computed ) {
+                                               ret = curCSS( elem, "margin-right", "marginRight" );
+                                       } else {
+                                               ret = elem.style.marginRight;
+                                       }
+                               });
+                               return ret;
+                       }
+               };
+       }
+});
+
+if ( document.defaultView && document.defaultView.getComputedStyle ) {
+       getComputedStyle = function( elem, name ) {
+               var ret, defaultView, computedStyle;
+
+               name = name.replace( rupper, "-$1" ).toLowerCase();
+
+               if ( (defaultView = elem.ownerDocument.defaultView) &&
+                               (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
+                       ret = computedStyle.getPropertyValue( name );
+                       if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
+                               ret = jQuery.style( elem, name );
+                       }
+               }
+
+               return ret;
+       };
+}
+
+if ( document.documentElement.currentStyle ) {
+       currentStyle = function( elem, name ) {
+               var left, rsLeft, uncomputed,
+                       ret = elem.currentStyle && elem.currentStyle[ name ],
+                       style = elem.style;
+
+               // Avoid setting ret to empty string here
+               // so we don't default to auto
+               if ( ret === null && style && (uncomputed = style[ name ]) ) {
+                       ret = uncomputed;
+               }
+
+               // From the awesome hack by Dean Edwards
+               // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+               // If we're not dealing with a regular pixel number
+               // but a number that has a weird ending, we need to convert it to pixels
+               if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
+
+                       // Remember the original values
+                       left = style.left;
+                       rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;
+
+                       // Put in the new values to get a computed value out
+                       if ( rsLeft ) {
+                               elem.runtimeStyle.left = elem.currentStyle.left;
+                       }
+                       style.left = name === "fontSize" ? "1em" : ( ret || 0 );
+                       ret = style.pixelLeft + "px";
+
+                       // Revert the changed values
+                       style.left = left;
+                       if ( rsLeft ) {
+                               elem.runtimeStyle.left = rsLeft;
+                       }
+               }
+
+               return ret === "" ? "auto" : ret;
+       };
+}
+
+curCSS = getComputedStyle || currentStyle;
+
+function getWH( elem, name, extra ) {
+
+       // Start with offset property
+       var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+               which = name === "width" ? cssWidth : cssHeight,
+               i = 0,
+               len = which.length;
+
+       if ( val > 0 ) {
+               if ( extra !== "border" ) {
+                       for ( ; i < len; i++ ) {
+                               if ( !extra ) {
+                                       val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+                               }
+                               if ( extra === "margin" ) {
+                                       val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+                               } else {
+                                       val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+                               }
+                       }
+               }
+
+               return val + "px";
+       }
+
+       // Fall back to computed then uncomputed css if necessary
+       val = curCSS( elem, name, name );
+       if ( val < 0 || val == null ) {
+               val = elem.style[ name ] || 0;
+       }
+       // Normalize "", auto, and prepare for extra
+       val = parseFloat( val ) || 0;
+
+       // Add padding, border, margin
+       if ( extra ) {
+               for ( ; i < len; i++ ) {
+                       val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
+                       if ( extra !== "padding" ) {
+                               val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
+                       }
+                       if ( extra === "margin" ) {
+                               val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
+                       }
+               }
+       }
+
+       return val + "px";
+}
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+       jQuery.expr.filters.hidden = function( elem ) {
+               var width = elem.offsetWidth,
+                       height = elem.offsetHeight;
+
+               return ( width === 0 && height === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+       };
+
+       jQuery.expr.filters.visible = function( elem ) {
+               return !jQuery.expr.filters.hidden( elem );
+       };
+}
+
+
+
+
+var r20 = /%20/g,
+       rbracket = /\[\]$/,
+       rCRLF = /\r?\n/g,
+       rhash = /#.*$/,
+       rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+       rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+       // #7653, #8125, #8152: local protocol detection
+       rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
+       rnoContent = /^(?:GET|HEAD)$/,
+       rprotocol = /^\/\//,
+       rquery = /\?/,
+       rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+       rselectTextarea = /^(?:select|textarea)/i,
+       rspacesAjax = /\s+/,
+       rts = /([?&])_=[^&]*/,
+       rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
+
+       // Keep a copy of the old load method
+       _load = jQuery.fn.load,
+
+       /* Prefilters
+        * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+        * 2) These are called:
+        *    - BEFORE asking for a transport
+        *    - AFTER param serialization (s.data is a string if s.processData is true)
+        * 3) key is the dataType
+        * 4) the catchall symbol "*" can be used
+        * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+        */
+       prefilters = {},
+
+       /* Transports bindings
+        * 1) key is the dataType
+        * 2) the catchall symbol "*" can be used
+        * 3) selection will start with transport dataType and THEN go to "*" if needed
+        */
+       transports = {},
+
+       // Document location
+       ajaxLocation,
+
+       // Document location segments
+       ajaxLocParts,
+
+       // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+       allTypes = ["*/"] + ["*"];
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+       ajaxLocation = location.href;
+} catch( e ) {
+       // Use the href attribute of an A element
+       // since IE will modify it given document.location
+       ajaxLocation = document.createElement( "a" );
+       ajaxLocation.href = "";
+       ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+       // dataTypeExpression is optional and defaults to "*"
+       return function( dataTypeExpression, func ) {
+
+               if ( typeof dataTypeExpression !== "string" ) {
+                       func = dataTypeExpression;
+                       dataTypeExpression = "*";
+               }
+
+               if ( jQuery.isFunction( func ) ) {
+                       var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
+                               i = 0,
+                               length = dataTypes.length,
+                               dataType,
+                               list,
+                               placeBefore;
+
+                       // For each dataType in the dataTypeExpression
+                       for ( ; i < length; i++ ) {
+                               dataType = dataTypes[ i ];
+                               // We control if we're asked to add before
+                               // any existing element
+                               placeBefore = /^\+/.test( dataType );
+                               if ( placeBefore ) {
+                                       dataType = dataType.substr( 1 ) || "*";
+                               }
+                               list = structure[ dataType ] = structure[ dataType ] || [];
+                               // then we add to the structure accordingly
+                               list[ placeBefore ? "unshift" : "push" ]( func );
+                       }
+               }
+       };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
+               dataType /* internal */, inspected /* internal */ ) {
+
+       dataType = dataType || options.dataTypes[ 0 ];
+       inspected = inspected || {};
+
+       inspected[ dataType ] = true;
+
+       var list = structure[ dataType ],
+               i = 0,
+               length = list ? list.length : 0,
+               executeOnly = ( structure === prefilters ),
+               selection;
+
+       for ( ; i < length && ( executeOnly || !selection ); i++ ) {
+               selection = list[ i ]( options, originalOptions, jqXHR );
+               // If we got redirected to another dataType
+               // we try there if executing only and not done already
+               if ( typeof selection === "string" ) {
+                       if ( !executeOnly || inspected[ selection ] ) {
+                               selection = undefined;
+                       } else {
+                               options.dataTypes.unshift( selection );
+                               selection = inspectPrefiltersOrTransports(
+                                               structure, options, originalOptions, jqXHR, selection, inspected );
+                       }
+               }
+       }
+       // If we're only executing or nothing was selected
+       // we try the catchall dataType if not done already
+       if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
+               selection = inspectPrefiltersOrTransports(
+                               structure, options, originalOptions, jqXHR, "*", inspected );
+       }
+       // unnecessary when only executing (prefilters)
+       // but it'll be ignored by the caller in that case
+       return selection;
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+       var key, deep,
+               flatOptions = jQuery.ajaxSettings.flatOptions || {};
+       for ( key in src ) {
+               if ( src[ key ] !== undefined ) {
+                       ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+               }
+       }
+       if ( deep ) {
+               jQuery.extend( true, target, deep );
+       }
+}
+
+jQuery.fn.extend({
+       load: function( url, params, callback ) {
+               if ( typeof url !== "string" && _load ) {
+                       return _load.apply( this, arguments );
+
+               // Don't do a request if no elements are being requested
+               } else if ( !this.length ) {
+                       return this;
+               }
+
+               var off = url.indexOf( " " );
+               if ( off >= 0 ) {
+                       var selector = url.slice( off, url.length );
+                       url = url.slice( 0, off );
+               }
+
+               // Default to a GET request
+               var type = "GET";
+
+               // If the second parameter was provided
+               if ( params ) {
+                       // If it's a function
+                       if ( jQuery.isFunction( params ) ) {
+                               // We assume that it's the callback
+                               callback = params;
+                               params = undefined;
+
+                       // Otherwise, build a param string
+                       } else if ( typeof params === "object" ) {
+                               params = jQuery.param( params, jQuery.ajaxSettings.traditional );
+                               type = "POST";
+                       }
+               }
+
+               var self = this;
+
+               // Request the remote document
+               jQuery.ajax({
+                       url: url,
+                       type: type,
+                       dataType: "html",
+                       data: params,
+                       // Complete callback (responseText is used internally)
+                       complete: function( jqXHR, status, responseText ) {
+                               // Store the response as specified by the jqXHR object
+                               responseText = jqXHR.responseText;
+                               // If successful, inject the HTML into all the matched elements
+                               if ( jqXHR.isResolved() ) {
+                                       // #4825: Get the actual response in case
+                                       // a dataFilter is present in ajaxSettings
+                                       jqXHR.done(function( r ) {
+                                               responseText = r;
+                                       });
+                                       // See if a selector was specified
+                                       self.html( selector ?
+                                               // Create a dummy div to hold the results
+                                               jQuery("<div>")
+                                                       // inject the contents of the document in, removing the scripts
+                                                       // to avoid any 'Permission Denied' errors in IE
+                                                       .append(responseText.replace(rscript, ""))
+
+                                                       // Locate the specified elements
+                                                       .find(selector) :
+
+                                               // If not, just inject the full result
+                                               responseText );
+                               }
+
+                               if ( callback ) {
+                                       self.each( callback, [ responseText, status, jqXHR ] );
+                               }
+                       }
+               });
+
+               return this;
+       },
+
+       serialize: function() {
+               return jQuery.param( this.serializeArray() );
+       },
+
+       serializeArray: function() {
+               return this.map(function(){
+                       return this.elements ? jQuery.makeArray( this.elements ) : this;
+               })
+               .filter(function(){
+                       return this.name && !this.disabled &&
+                               ( this.checked || rselectTextarea.test( this.nodeName ) ||
+                                       rinput.test( this.type ) );
+               })
+               .map(function( i, elem ){
+                       var val = jQuery( this ).val();
+
+                       return val == null ?
+                               null :
+                               jQuery.isArray( val ) ?
+                                       jQuery.map( val, function( val, i ){
+                                               return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+                                       }) :
+                                       { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+               }).get();
+       }
+});
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
+       jQuery.fn[ o ] = function( f ){
+               return this.on( o, f );
+       };
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+       jQuery[ method ] = function( url, data, callback, type ) {
+               // shift arguments if data argument was omitted
+               if ( jQuery.isFunction( data ) ) {
+                       type = type || callback;
+                       callback = data;
+                       data = undefined;
+               }
+
+               return jQuery.ajax({
+                       type: method,
+                       url: url,
+                       data: data,
+                       success: callback,
+                       dataType: type
+               });
+       };
+});
+
+jQuery.extend({
+
+       getScript: function( url, callback ) {
+               return jQuery.get( url, undefined, callback, "script" );
+       },
+
+       getJSON: function( url, data, callback ) {
+               return jQuery.get( url, data, callback, "json" );
+       },
+
+       // Creates a full fledged settings object into target
+       // with both ajaxSettings and settings fields.
+       // If target is omitted, writes into ajaxSettings.
+       ajaxSetup: function( target, settings ) {
+               if ( settings ) {
+                       // Building a settings object
+                       ajaxExtend( target, jQuery.ajaxSettings );
+               } else {
+                       // Extending ajaxSettings
+                       settings = target;
+                       target = jQuery.ajaxSettings;
+               }
+               ajaxExtend( target, settings );
+               return target;
+       },
+
+       ajaxSettings: {
+               url: ajaxLocation,
+               isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+               global: true,
+               type: "GET",
+               contentType: "application/x-www-form-urlencoded",
+               processData: true,
+               async: true,
+               /*
+               timeout: 0,
+               data: null,
+               dataType: null,
+               username: null,
+               password: null,
+               cache: null,
+               traditional: false,
+               headers: {},
+               */
+
+               accepts: {
+                       xml: "application/xml, text/xml",
+                       html: "text/html",
+                       text: "text/plain",
+                       json: "application/json, text/javascript",
+                       "*": allTypes
+               },
+
+               contents: {
+                       xml: /xml/,
+                       html: /html/,
+                       json: /json/
+               },
+
+               responseFields: {
+                       xml: "responseXML",
+                       text: "responseText"
+               },
+
+               // List of data converters
+               // 1) key format is "source_type destination_type" (a single space in-between)
+               // 2) the catchall symbol "*" can be used for source_type
+               converters: {
+
+                       // Convert anything to text
+                       "* text": window.String,
+
+                       // Text to html (true = no transformation)
+                       "text html": true,
+
+                       // Evaluate text as a json expression
+                       "text json": jQuery.parseJSON,
+
+                       // Parse text as xml
+                       "text xml": jQuery.parseXML
+               },
+
+               // For options that shouldn't be deep extended:
+               // you can add your own custom options here if
+               // and when you create one that shouldn't be
+               // deep extended (see ajaxExtend)
+               flatOptions: {
+                       context: true,
+                       url: true
+               }
+       },
+
+       ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+       ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+       // Main method
+       ajax: function( url, options ) {
+
+               // If url is an object, simulate pre-1.5 signature
+               if ( typeof url === "object" ) {
+                       options = url;
+                       url = undefined;
+               }
+
+               // Force options to be an object
+               options = options || {};
+
+               var // Create the final options object
+                       s = jQuery.ajaxSetup( {}, options ),
+                       // Callbacks context
+                       callbackContext = s.context || s,
+                       // Context for global events
+                       // It's the callbackContext if one was provided in the options
+                       // and if it's a DOM node or a jQuery collection
+                       globalEventContext = callbackContext !== s &&
+                               ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
+                                               jQuery( callbackContext ) : jQuery.event,
+                       // Deferreds
+                       deferred = jQuery.Deferred(),
+                       completeDeferred = jQuery.Callbacks( "once memory" ),
+                       // Status-dependent callbacks
+                       statusCode = s.statusCode || {},
+                       // ifModified key
+                       ifModifiedKey,
+                       // Headers (they are sent all at once)
+                       requestHeaders = {},
+                       requestHeadersNames = {},
+                       // Response headers
+                       responseHeadersString,
+                       responseHeaders,
+                       // transport
+                       transport,
+                       // timeout handle
+                       timeoutTimer,
+                       // Cross-domain detection vars
+                       parts,
+                       // The jqXHR state
+                       state = 0,
+                       // To know if global events are to be dispatched
+                       fireGlobals,
+                       // Loop variable
+                       i,
+                       // Fake xhr
+                       jqXHR = {
+
+                               readyState: 0,
+
+                               // Caches the header
+                               setRequestHeader: function( name, value ) {
+                                       if ( !state ) {
+                                               var lname = name.toLowerCase();
+                                               name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+                                               requestHeaders[ name ] = value;
+                                       }
+                                       return this;
+                               },
+
+                               // Raw string
+                               getAllResponseHeaders: function() {
+                                       return state === 2 ? responseHeadersString : null;
+                               },
+
+                               // Builds headers hashtable if needed
+                               getResponseHeader: function( key ) {
+                                       var match;
+                                       if ( state === 2 ) {
+                                               if ( !responseHeaders ) {
+                                                       responseHeaders = {};
+                                                       while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+                                                               responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+                                                       }
+                                               }
+                                               match = responseHeaders[ key.toLowerCase() ];
+                                       }
+                                       return match === undefined ? null : match;
+                               },
+
+                               // Overrides response content-type header
+                               overrideMimeType: function( type ) {
+                                       if ( !state ) {
+                                               s.mimeType = type;
+                                       }
+                                       return this;
+                               },
+
+                               // Cancel the request
+                               abort: function( statusText ) {
+                                       statusText = statusText || "abort";
+                                       if ( transport ) {
+                                               transport.abort( statusText );
+                                       }
+                                       done( 0, statusText );
+                                       return this;
+                               }
+                       };
+
+               // Callback for when everything is done
+               // It is defined here because jslint complains if it is declared
+               // at the end of the function (which would be more logical and readable)
+               function done( status, nativeStatusText, responses, headers ) {
+
+                       // Called once
+                       if ( state === 2 ) {
+                               return;
+                       }
+
+                       // State is "done" now
+                       state = 2;
+
+                       // Clear timeout if it exists
+                       if ( timeoutTimer ) {
+                               clearTimeout( timeoutTimer );
+                       }
+
+                       // Dereference transport for early garbage collection
+                       // (no matter how long the jqXHR object will be used)
+                       transport = undefined;
+
+                       // Cache response headers
+                       responseHeadersString = headers || "";
+
+                       // Set readyState
+                       jqXHR.readyState = status > 0 ? 4 : 0;
+
+                       var isSuccess,
+                               success,
+                               error,
+                               statusText = nativeStatusText,
+                               response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
+                               lastModified,
+                               etag;
+
+                       // If successful, handle type chaining
+                       if ( status >= 200 && status < 300 || status === 304 ) {
+
+                               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+                               if ( s.ifModified ) {
+
+                                       if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
+                                               jQuery.lastModified[ ifModifiedKey ] = lastModified;
+                                       }
+                                       if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
+                                               jQuery.etag[ ifModifiedKey ] = etag;
+                                       }
+                               }
+
+                               // If not modified
+                               if ( status === 304 ) {
+
+                                       statusText = "notmodified";
+                                       isSuccess = true;
+
+                               // If we have data
+                               } else {
+
+                                       try {
+                                               success = ajaxConvert( s, response );
+                                               statusText = "success";
+                                               isSuccess = true;
+                                       } catch(e) {
+                                               // We have a parsererror
+                                               statusText = "parsererror";
+                                               error = e;
+                                       }
+                               }
+                       } else {
+                               // We extract error from statusText
+                               // then normalize statusText and status for non-aborts
+                               error = statusText;
+                               if ( !statusText || status ) {
+                                       statusText = "error";
+                                       if ( status < 0 ) {
+                                               status = 0;
+                                       }
+                               }
+                       }
+
+                       // Set data for the fake xhr object
+                       jqXHR.status = status;
+                       jqXHR.statusText = "" + ( nativeStatusText || statusText );
+
+                       // Success/Error
+                       if ( isSuccess ) {
+                               deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+                       } else {
+                               deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+                       }
+
+                       // Status-dependent callbacks
+                       jqXHR.statusCode( statusCode );
+                       statusCode = undefined;
+
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
+                                               [ jqXHR, s, isSuccess ? success : error ] );
+                       }
+
+                       // Complete
+                       completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+                               // Handle the global AJAX counter
+                               if ( !( --jQuery.active ) ) {
+                                       jQuery.event.trigger( "ajaxStop" );
+                               }
+                       }
+               }
+
+               // Attach deferreds
+               deferred.promise( jqXHR );
+               jqXHR.success = jqXHR.done;
+               jqXHR.error = jqXHR.fail;
+               jqXHR.complete = completeDeferred.add;
+
+               // Status-dependent callbacks
+               jqXHR.statusCode = function( map ) {
+                       if ( map ) {
+                               var tmp;
+                               if ( state < 2 ) {
+                                       for ( tmp in map ) {
+                                               statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
+                                       }
+                               } else {
+                                       tmp = map[ jqXHR.status ];
+                                       jqXHR.then( tmp, tmp );
+                               }
+                       }
+                       return this;
+               };
+
+               // Remove hash character (#7531: and string promotion)
+               // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+               // We also use the url parameter if available
+               s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+               // Extract dataTypes list
+               s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
+
+               // Determine if a cross-domain request is in order
+               if ( s.crossDomain == null ) {
+                       parts = rurl.exec( s.url.toLowerCase() );
+                       s.crossDomain = !!( parts &&
+                               ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
+                                       ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
+                                               ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
+                       );
+               }
+
+               // Convert data if not already a string
+               if ( s.data && s.processData && typeof s.data !== "string" ) {
+                       s.data = jQuery.param( s.data, s.traditional );
+               }
+
+               // Apply prefilters
+               inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+               // If request was aborted inside a prefiler, stop there
+               if ( state === 2 ) {
+                       return false;
+               }
+
+               // We can fire global events as of now if asked to
+               fireGlobals = s.global;
+
+               // Uppercase the type
+               s.type = s.type.toUpperCase();
+
+               // Determine if request has content
+               s.hasContent = !rnoContent.test( s.type );
+
+               // Watch for a new set of requests
+               if ( fireGlobals && jQuery.active++ === 0 ) {
+                       jQuery.event.trigger( "ajaxStart" );
+               }
+
+               // More options handling for requests with no content
+               if ( !s.hasContent ) {
+
+                       // If data is available, append data to url
+                       if ( s.data ) {
+                               s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+                               // #9682: remove data so that it's not used in an eventual retry
+                               delete s.data;
+                       }
+
+                       // Get ifModifiedKey before adding the anti-cache parameter
+                       ifModifiedKey = s.url;
+
+                       // Add anti-cache in url if needed
+                       if ( s.cache === false ) {
+
+                               var ts = jQuery.now(),
+                                       // try replacing _= if it is there
+                                       ret = s.url.replace( rts, "$1_=" + ts );
+
+                               // if nothing was replaced, add timestamp to the end
+                               s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
+                       }
+               }
+
+               // Set the correct header, if data is being sent
+               if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+                       jqXHR.setRequestHeader( "Content-Type", s.contentType );
+               }
+
+               // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+               if ( s.ifModified ) {
+                       ifModifiedKey = ifModifiedKey || s.url;
+                       if ( jQuery.lastModified[ ifModifiedKey ] ) {
+                               jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
+                       }
+                       if ( jQuery.etag[ ifModifiedKey ] ) {
+                               jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
+                       }
+               }
+
+               // Set the Accepts header for the server, depending on the dataType
+               jqXHR.setRequestHeader(
+                       "Accept",
+                       s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+                               s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+                               s.accepts[ "*" ]
+               );
+
+               // Check for headers option
+               for ( i in s.headers ) {
+                       jqXHR.setRequestHeader( i, s.headers[ i ] );
+               }
+
+               // Allow custom headers/mimetypes and early abort
+               if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+                               // Abort if not done already
+                               jqXHR.abort();
+                               return false;
+
+               }
+
+               // Install callbacks on deferreds
+               for ( i in { success: 1, error: 1, complete: 1 } ) {
+                       jqXHR[ i ]( s[ i ] );
+               }
+
+               // Get transport
+               transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+               // If no transport, we auto-abort
+               if ( !transport ) {
+                       done( -1, "No Transport" );
+               } else {
+                       jqXHR.readyState = 1;
+                       // Send global event
+                       if ( fireGlobals ) {
+                               globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+                       }
+                       // Timeout
+                       if ( s.async && s.timeout > 0 ) {
+                               timeoutTimer = setTimeout( function(){
+                                       jqXHR.abort( "timeout" );
+                               }, s.timeout );
+                       }
+
+                       try {
+                               state = 1;
+                               transport.send( requestHeaders, done );
+                       } catch (e) {
+                               // Propagate exception as error if not done
+                               if ( state < 2 ) {
+                                       done( -1, e );
+                               // Simply rethrow otherwise
+                               } else {
+                                       throw e;
+                               }
+                       }
+               }
+
+               return jqXHR;
+       },
+
+       // Serialize an array of form elements or a set of
+       // key/values into a query string
+       param: function( a, traditional ) {
+               var s = [],
+                       add = function( key, value ) {
+                               // If value is a function, invoke it and return its value
+                               value = jQuery.isFunction( value ) ? value() : value;
+                               s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+                       };
+
+               // Set traditional to true for jQuery <= 1.3.2 behavior.
+               if ( traditional === undefined ) {
+                       traditional = jQuery.ajaxSettings.traditional;
+               }
+
+               // If an array was passed in, assume that it is an array of form elements.
+               if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+                       // Serialize the form elements
+                       jQuery.each( a, function() {
+                               add( this.name, this.value );
+                       });
+
+               } else {
+                       // If traditional, encode the "old" way (the way 1.3.2 or older
+                       // did it), otherwise encode params recursively.
+                       for ( var prefix in a ) {
+                               buildParams( prefix, a[ prefix ], traditional, add );
+                       }
+               }
+
+               // Return the resulting serialization
+               return s.join( "&" ).replace( r20, "+" );
+       }
+});
+
+function buildParams( prefix, obj, traditional, add ) {
+       if ( jQuery.isArray( obj ) ) {
+               // Serialize array item.
+               jQuery.each( obj, function( i, v ) {
+                       if ( traditional || rbracket.test( prefix ) ) {
+                               // Treat each array item as a scalar.
+                               add( prefix, v );
+
+                       } else {
+                               // If array item is non-scalar (array or object), encode its
+                               // numeric index to resolve deserialization ambiguity issues.
+                               // Note that rack (as of 1.0.0) can't currently deserialize
+                               // nested arrays properly, and attempting to do so may cause
+                               // a server error. Possible fixes are to modify rack's
+                               // deserialization algorithm or to provide an option or flag
+                               // to force array serialization to be shallow.
+                               buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
+                       }
+               });
+
+       } else if ( !traditional && obj != null && typeof obj === "object" ) {
+               // Serialize object item.
+               for ( var name in obj ) {
+                       buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+               }
+
+       } else {
+               // Serialize scalar item.
+               add( prefix, obj );
+       }
+}
+
+// This is still on the jQuery object... for now
+// Want to move this to jQuery.ajax some day
+jQuery.extend({
+
+       // Counter for holding the number of active queries
+       active: 0,
+
+       // Last-Modified header cache for next request
+       lastModified: {},
+       etag: {}
+
+});
+
+/* Handles responses to an ajax request:
+ * - sets all responseXXX fields accordingly
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+       var contents = s.contents,
+               dataTypes = s.dataTypes,
+               responseFields = s.responseFields,
+               ct,
+               type,
+               finalDataType,
+               firstDataType;
+
+       // Fill responseXXX fields
+       for ( type in responseFields ) {
+               if ( type in responses ) {
+                       jqXHR[ responseFields[type] ] = responses[ type ];
+               }
+       }
+
+       // Remove auto dataType and get content-type in the process
+       while( dataTypes[ 0 ] === "*" ) {
+               dataTypes.shift();
+               if ( ct === undefined ) {
+                       ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
+               }
+       }
+
+       // Check if we're dealing with a known content-type
+       if ( ct ) {
+               for ( type in contents ) {
+                       if ( contents[ type ] && contents[ type ].test( ct ) ) {
+                               dataTypes.unshift( type );
+                               break;
+                       }
+               }
+       }
+
+       // Check to see if we have a response for the expected dataType
+       if ( dataTypes[ 0 ] in responses ) {
+               finalDataType = dataTypes[ 0 ];
+       } else {
+               // Try convertible dataTypes
+               for ( type in responses ) {
+                       if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+                               finalDataType = type;
+                               break;
+                       }
+                       if ( !firstDataType ) {
+                               firstDataType = type;
+                       }
+               }
+               // Or just use first one
+               finalDataType = finalDataType || firstDataType;
+       }
+
+       // If we found a dataType
+       // We add the dataType to the list if needed
+       // and return the corresponding response
+       if ( finalDataType ) {
+               if ( finalDataType !== dataTypes[ 0 ] ) {
+                       dataTypes.unshift( finalDataType );
+               }
+               return responses[ finalDataType ];
+       }
+}
+
+// Chain conversions given the request and the original response
+function ajaxConvert( s, response ) {
+
+       // Apply the dataFilter if provided
+       if ( s.dataFilter ) {
+               response = s.dataFilter( response, s.dataType );
+       }
+
+       var dataTypes = s.dataTypes,
+               converters = {},
+               i,
+               key,
+               length = dataTypes.length,
+               tmp,
+               // Current and previous dataTypes
+               current = dataTypes[ 0 ],
+               prev,
+               // Conversion expression
+               conversion,
+               // Conversion function
+               conv,
+               // Conversion functions (transitive conversion)
+               conv1,
+               conv2;
+
+       // For each dataType in the chain
+       for ( i = 1; i < length; i++ ) {
+
+               // Create converters map
+               // with lowercased keys
+               if ( i === 1 ) {
+                       for ( key in s.converters ) {
+                               if ( typeof key === "string" ) {
+                                       converters[ key.toLowerCase() ] = s.converters[ key ];
+                               }
+                       }
+               }
+
+               // Get the dataTypes
+               prev = current;
+               current = dataTypes[ i ];
+
+               // If current is auto dataType, update it to prev
+               if ( current === "*" ) {
+                       current = prev;
+               // If no auto and dataTypes are actually different
+               } else if ( prev !== "*" && prev !== current ) {
+
+                       // Get the converter
+                       conversion = prev + " " + current;
+                       conv = converters[ conversion ] || converters[ "* " + current ];
+
+                       // If there is no direct converter, search transitively
+                       if ( !conv ) {
+                               conv2 = undefined;
+                               for ( conv1 in converters ) {
+                                       tmp = conv1.split( " " );
+                                       if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
+                                               conv2 = converters[ tmp[1] + " " + current ];
+                                               if ( conv2 ) {
+                                                       conv1 = converters[ conv1 ];
+                                                       if ( conv1 === true ) {
+                                                               conv = conv2;
+                                                       } else if ( conv2 === true ) {
+                                                               conv = conv1;
+                                                       }
+                                                       break;
+                                               }
+                                       }
+                               }
+                       }
+                       // If we found no converter, dispatch an error
+                       if ( !( conv || conv2 ) ) {
+                               jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
+                       }
+                       // If found converter is not an equivalence
+                       if ( conv !== true ) {
+                               // Convert with 1 or 2 converters accordingly
+                               response = conv ? conv( response ) : conv2( conv1(response) );
+                       }
+               }
+       }
+       return response;
+}
+
+
+
+
+var jsc = jQuery.now(),
+       jsre = /(\=)\?(&|$)|\?\?/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+       jsonp: "callback",
+       jsonpCallback: function() {
+               return jQuery.expando + "_" + ( jsc++ );
+       }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+       var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
+               ( typeof s.data === "string" );
+
+       if ( s.dataTypes[ 0 ] === "jsonp" ||
+               s.jsonp !== false && ( jsre.test( s.url ) ||
+                               inspectData && jsre.test( s.data ) ) ) {
+
+               var responseContainer,
+                       jsonpCallback = s.jsonpCallback =
+                               jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+                       previous = window[ jsonpCallback ],
+                       url = s.url,
+                       data = s.data,
+                       replace = "$1" + jsonpCallback + "$2";
+
+               if ( s.jsonp !== false ) {
+                       url = url.replace( jsre, replace );
+                       if ( s.url === url ) {
+                               if ( inspectData ) {
+                                       data = data.replace( jsre, replace );
+                               }
+                               if ( s.data === data ) {
+                                       // Add callback manually
+                                       url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+                               }
+                       }
+               }
+
+               s.url = url;
+               s.data = data;
+
+               // Install callback
+               window[ jsonpCallback ] = function( response ) {
+                       responseContainer = [ response ];
+               };
+
+               // Clean-up function
+               jqXHR.always(function() {
+                       // Set callback back to previous value
+                       window[ jsonpCallback ] = previous;
+                       // Call if it was a function and we have a response
+                       if ( responseContainer && jQuery.isFunction( previous ) ) {
+                               window[ jsonpCallback ]( responseContainer[ 0 ] );
+                       }
+               });
+
+               // Use data converter to retrieve json after script execution
+               s.converters["script json"] = function() {
+                       if ( !responseContainer ) {
+                               jQuery.error( jsonpCallback + " was not called" );
+                       }
+                       return responseContainer[ 0 ];
+               };
+
+               // force json dataType
+               s.dataTypes[ 0 ] = "json";
+
+               // Delegate to script
+               return "script";
+       }
+});
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+       accepts: {
+               script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+       },
+       contents: {
+               script: /javascript|ecmascript/
+       },
+       converters: {
+               "text script": function( text ) {
+                       jQuery.globalEval( text );
+                       return text;
+               }
+       }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+       if ( s.cache === undefined ) {
+               s.cache = false;
+       }
+       if ( s.crossDomain ) {
+               s.type = "GET";
+               s.global = false;
+       }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+       // This transport only deals with cross domain requests
+       if ( s.crossDomain ) {
+
+               var script,
+                       head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
+
+               return {
+
+                       send: function( _, callback ) {
+
+                               script = document.createElement( "script" );
+
+                               script.async = "async";
+
+                               if ( s.scriptCharset ) {
+                                       script.charset = s.scriptCharset;
+                               }
+
+                               script.src = s.url;
+
+                               // Attach handlers for all browsers
+                               script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+                                       if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+                                               // Handle memory leak in IE
+                                               script.onload = script.onreadystatechange = null;
+
+                                               // Remove the script
+                                               if ( head && script.parentNode ) {
+                                                       head.removeChild( script );
+                                               }
+
+                                               // Dereference the script
+                                               script = undefined;
+
+                                               // Callback if not abort
+                                               if ( !isAbort ) {
+                                                       callback( 200, "success" );
+                                               }
+                                       }
+                               };
+                               // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
+                               // This arises when a base node is used (#2709 and #4378).
+                               head.insertBefore( script, head.firstChild );
+                       },
+
+                       abort: function() {
+                               if ( script ) {
+                                       script.onload( 0, 1 );
+                               }
+                       }
+               };
+       }
+});
+
+
+
+
+var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
+       xhrOnUnloadAbort = window.ActiveXObject ? function() {
+               // Abort all pending requests
+               for ( var key in xhrCallbacks ) {
+                       xhrCallbacks[ key ]( 0, 1 );
+               }
+       } : false,
+       xhrId = 0,
+       xhrCallbacks;
+
+// Functions to create xhrs
+function createStandardXHR() {
+       try {
+               return new window.XMLHttpRequest();
+       } catch( e ) {}
+}
+
+function createActiveXHR() {
+       try {
+               return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+       } catch( e ) {}
+}
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject ?
+       /* Microsoft failed to properly
+        * implement the XMLHttpRequest in IE7 (can't request local files),
+        * so we use the ActiveXObject when it is available
+        * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+        * we need a fallback.
+        */
+       function() {
+               return !this.isLocal && createStandardXHR() || createActiveXHR();
+       } :
+       // For all other browsers, use the standard XMLHttpRequest object
+       createStandardXHR;
+
+// Determine support properties
+(function( xhr ) {
+       jQuery.extend( jQuery.support, {
+               ajax: !!xhr,
+               cors: !!xhr && ( "withCredentials" in xhr )
+       });
+})( jQuery.ajaxSettings.xhr() );
+
+// Create transport if the browser can provide an xhr
+if ( jQuery.support.ajax ) {
+
+       jQuery.ajaxTransport(function( s ) {
+               // Cross domain only allowed if supported through XMLHttpRequest
+               if ( !s.crossDomain || jQuery.support.cors ) {
+
+                       var callback;
+
+                       return {
+                               send: function( headers, complete ) {
+
+                                       // Get a new xhr
+                                       var xhr = s.xhr(),
+                                               handle,
+                                               i;
+
+                                       // Open the socket
+                                       // Passing null username, generates a login popup on Opera (#2865)
+                                       if ( s.username ) {
+                                               xhr.open( s.type, s.url, s.async, s.username, s.password );
+                                       } else {
+                                               xhr.open( s.type, s.url, s.async );
+                                       }
+
+                                       // Apply custom fields if provided
+                                       if ( s.xhrFields ) {
+                                               for ( i in s.xhrFields ) {
+                                                       xhr[ i ] = s.xhrFields[ i ];
+                                               }
+                                       }
+
+                                       // Override mime type if needed
+                                       if ( s.mimeType && xhr.overrideMimeType ) {
+                                               xhr.overrideMimeType( s.mimeType );
+                                       }
+
+                                       // X-Requested-With header
+                                       // For cross-domain requests, seeing as conditions for a preflight are
+                                       // akin to a jigsaw puzzle, we simply never set it to be sure.
+                                       // (it can always be set on a per-request basis or even using ajaxSetup)
+                                       // For same-domain requests, won't change header if already provided.
+                                       if ( !s.crossDomain && !headers["X-Requested-With"] ) {
+                                               headers[ "X-Requested-With" ] = "XMLHttpRequest";
+                                       }
+
+                                       // Need an extra try/catch for cross domain requests in Firefox 3
+                                       try {
+                                               for ( i in headers ) {
+                                                       xhr.setRequestHeader( i, headers[ i ] );
+                                               }
+                                       } catch( _ ) {}
+
+                                       // Do send the request
+                                       // This may raise an exception which is actually
+                                       // handled in jQuery.ajax (so no try/catch here)
+                                       xhr.send( ( s.hasContent && s.data ) || null );
+
+                                       // Listener
+                                       callback = function( _, isAbort ) {
+
+                                               var status,
+                                                       statusText,
+                                                       responseHeaders,
+                                                       responses,
+                                                       xml;
+
+                                               // Firefox throws exceptions when accessing properties
+                                               // of an xhr when a network error occured
+                                               // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
+                                               try {
+
+                                                       // Was never called and is aborted or complete
+                                                       if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+                                                               // Only called once
+                                                               callback = undefined;
+
+                                                               // Do not keep as active anymore
+                                                               if ( handle ) {
+                                                                       xhr.onreadystatechange = jQuery.noop;
+                                                                       if ( xhrOnUnloadAbort ) {
+                                                                               delete xhrCallbacks[ handle ];
+                                                                       }
+                                                               }
+
+                                                               // If it's an abort
+                                                               if ( isAbort ) {
+                                                                       // Abort it manually if needed
+                                                                       if ( xhr.readyState !== 4 ) {
+                                                                               xhr.abort();
+                                                                       }
+                                                               } else {
+                                                                       status = xhr.status;
+                                                                       responseHeaders = xhr.getAllResponseHeaders();
+                                                                       responses = {};
+                                                                       xml = xhr.responseXML;
+
+                                                                       // Construct response list
+                                                                       if ( xml && xml.documentElement /* #4958 */ ) {
+                                                                               responses.xml = xml;
+                                                                       }
+                                                                       responses.text = xhr.responseText;
+
+                                                                       // Firefox throws an exception when accessing
+                                                                       // statusText for faulty cross-domain requests
+                                                                       try {
+                                                                               statusText = xhr.statusText;
+                                                                       } catch( e ) {
+                                                                               // We normalize with Webkit giving an empty statusText
+                                                                               statusText = "";
+                                                                       }
+
+                                                                       // Filter status for non standard behaviors
+
+                                                                       // If the request is local and we have data: assume a success
+                                                                       // (success with no data won't get notified, that's the best we
+                                                                       // can do given current implementations)
+                                                                       if ( !status && s.isLocal && !s.crossDomain ) {
+                                                                               status = responses.text ? 200 : 404;
+                                                                       // IE - #1450: sometimes returns 1223 when it should be 204
+                                                                       } else if ( status === 1223 ) {
+                                                                               status = 204;
+                                                                       }
+                                                               }
+                                                       }
+                                               } catch( firefoxAccessException ) {
+                                                       if ( !isAbort ) {
+                                                               complete( -1, firefoxAccessException );
+                                                       }
+                                               }
+
+                                               // Call complete if needed
+                                               if ( responses ) {
+                                                       complete( status, statusText, responses, responseHeaders );
+                                               }
+                                       };
+
+                                       // if we're in sync mode or it's in cache
+                                       // and has been retrieved directly (IE6 & IE7)
+                                       // we need to manually fire the callback
+                                       if ( !s.async || xhr.readyState === 4 ) {
+                                               callback();
+                                       } else {
+                                               handle = ++xhrId;
+                                               if ( xhrOnUnloadAbort ) {
+                                                       // Create the active xhrs callbacks list if needed
+                                                       // and attach the unload handler
+                                                       if ( !xhrCallbacks ) {
+                                                               xhrCallbacks = {};
+                                                               jQuery( window ).unload( xhrOnUnloadAbort );
+                                                       }
+                                                       // Add to list of active xhrs callbacks
+                                                       xhrCallbacks[ handle ] = callback;
+                                               }
+                                               xhr.onreadystatechange = callback;
+                                       }
+                               },
+
+                               abort: function() {
+                                       if ( callback ) {
+                                               callback(0,1);
+                                       }
+                               }
+                       };
+               }
+       });
+}
+
+
+
+
+var elemdisplay = {},
+       iframe, iframeDoc,
+       rfxtypes = /^(?:toggle|show|hide)$/,
+       rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
+       timerId,
+       fxAttrs = [
+               // height animations
+               [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
+               // width animations
+               [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
+               // opacity animations
+               [ "opacity" ]
+       ],
+       fxNow;
+
+jQuery.fn.extend({
+       show: function( speed, easing, callback ) {
+               var elem, display;
+
+               if ( speed || speed === 0 ) {
+                       return this.animate( genFx("show", 3), speed, easing, callback );
+
+               } else {
+                       for ( var i = 0, j = this.length; i < j; i++ ) {
+                               elem = this[ i ];
+
+                               if ( elem.style ) {
+                                       display = elem.style.display;
+
+                                       // Reset the inline display of this element to learn if it is
+                                       // being hidden by cascaded rules or not
+                                       if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
+                                               display = elem.style.display = "";
+                                       }
+
+                                       // Set elements which have been overridden with display: none
+                                       // in a stylesheet to whatever the default browser style is
+                                       // for such an element
+                                       if ( display === "" && jQuery.css(elem, "display") === "none" ) {
+                                               jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+                                       }
+                               }
+                       }
+
+                       // Set the display of most of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( i = 0; i < j; i++ ) {
+                               elem = this[ i ];
+
+                               if ( elem.style ) {
+                                       display = elem.style.display;
+
+                                       if ( display === "" || display === "none" ) {
+                                               elem.style.display = jQuery._data( elem, "olddisplay" ) || "";
+                                       }
+                               }
+                       }
+
+                       return this;
+               }
+       },
+
+       hide: function( speed, easing, callback ) {
+               if ( speed || speed === 0 ) {
+                       return this.animate( genFx("hide", 3), speed, easing, callback);
+
+               } else {
+                       var elem, display,
+                               i = 0,
+                               j = this.length;
+
+                       for ( ; i < j; i++ ) {
+                               elem = this[i];
+                               if ( elem.style ) {
+                                       display = jQuery.css( elem, "display" );
+
+                                       if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
+                                               jQuery._data( elem, "olddisplay", display );
+                                       }
+                               }
+                       }
+
+                       // Set the display of the elements in a second loop
+                       // to avoid the constant reflow
+                       for ( i = 0; i < j; i++ ) {
+                               if ( this[i].style ) {
+                                       this[i].style.display = "none";
+                               }
+                       }
+
+                       return this;
+               }
+       },
+
+       // Save the old toggle function
+       _toggle: jQuery.fn.toggle,
+
+       toggle: function( fn, fn2, callback ) {
+               var bool = typeof fn === "boolean";
+
+               if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
+                       this._toggle.apply( this, arguments );
+
+               } else if ( fn == null || bool ) {
+                       this.each(function() {
+                               var state = bool ? fn : jQuery(this).is(":hidden");
+                               jQuery(this)[ state ? "show" : "hide" ]();
+                       });
+
+               } else {
+                       this.animate(genFx("toggle", 3), fn, fn2, callback);
+               }
+
+               return this;
+       },
+
+       fadeTo: function( speed, to, easing, callback ) {
+               return this.filter(":hidden").css("opacity", 0).show().end()
+                                       .animate({opacity: to}, speed, easing, callback);
+       },
+
+       animate: function( prop, speed, easing, callback ) {
+               var optall = jQuery.speed( speed, easing, callback );
+
+               if ( jQuery.isEmptyObject( prop ) ) {
+                       return this.each( optall.complete, [ false ] );
+               }
+
+               // Do not change referenced properties as per-property easing will be lost
+               prop = jQuery.extend( {}, prop );
+
+               function doAnimation() {
+                       // XXX 'this' does not always have a nodeName when running the
+                       // test suite
+
+                       if ( optall.queue === false ) {
+                               jQuery._mark( this );
+                       }
+
+                       var opt = jQuery.extend( {}, optall ),
+                               isElement = this.nodeType === 1,
+                               hidden = isElement && jQuery(this).is(":hidden"),
+                               name, val, p, e,
+                               parts, start, end, unit,
+                               method;
+
+                       // will store per property easing and be used to determine when an animation is complete
+                       opt.animatedProperties = {};
+
+                       for ( p in prop ) {
+
+                               // property name normalization
+                               name = jQuery.camelCase( p );
+                               if ( p !== name ) {
+                                       prop[ name ] = prop[ p ];
+                                       delete prop[ p ];
+                               }
+
+                               val = prop[ name ];
+
+                               // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
+                               if ( jQuery.isArray( val ) ) {
+                                       opt.animatedProperties[ name ] = val[ 1 ];
+                                       val = prop[ name ] = val[ 0 ];
+                               } else {
+                                       opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
+                               }
+
+                               if ( val === "hide" && hidden || val === "show" && !hidden ) {
+                                       return opt.complete.call( this );
+                               }
+
+                               if ( isElement && ( name === "height" || name === "width" ) ) {
+                                       // Make sure that nothing sneaks out
+                                       // Record all 3 overflow attributes because IE does not
+                                       // change the overflow attribute when overflowX and
+                                       // overflowY are set to the same value
+                                       opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
+
+                                       // Set display property to inline-block for height/width
+                                       // animations on inline elements that are having width/height animated
+                                       if ( jQuery.css( this, "display" ) === "inline" &&
+                                                       jQuery.css( this, "float" ) === "none" ) {
+
+                                               // inline-level elements accept inline-block;
+                                               // block-level elements need to be inline with layout
+                                               if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
+                                                       this.style.display = "inline-block";
+
+                                               } else {
+                                                       this.style.zoom = 1;
+                                               }
+                                       }
+                               }
+                       }
+
+                       if ( opt.overflow != null ) {
+                               this.style.overflow = "hidden";
+                       }
+
+                       for ( p in prop ) {
+                               e = new jQuery.fx( this, opt, p );
+                               val = prop[ p ];
+
+                               if ( rfxtypes.test( val ) ) {
+
+                                       // Tracks whether to show or hide based on private
+                                       // data attached to the element
+                                       method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
+                                       if ( method ) {
+                                               jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
+                                               e[ method ]();
+                                       } else {
+                                               e[ val ]();
+                                       }
+
+                               } else {
+                                       parts = rfxnum.exec( val );
+                                       start = e.cur();
+
+                                       if ( parts ) {
+                                               end = parseFloat( parts[2] );
+                                               unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );
+
+                                               // We need to compute starting value
+                                               if ( unit !== "px" ) {
+                                                       jQuery.style( this, p, (end || 1) + unit);
+                                                       start = ( (end || 1) / e.cur() ) * start;
+                                                       jQuery.style( this, p, start + unit);
+                                               }
+
+                                               // If a +=/-= token was provided, we're doing a relative animation
+                                               if ( parts[1] ) {
+                                                       end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) + start;
+                                               }
+
+                                               e.custom( start, end, unit );
+
+                                       } else {
+                                               e.custom( start, val, "" );
+                                       }
+                               }
+                       }
+
+                       // For JS strict compliance
+                       return true;
+               }
+
+               return optall.queue === false ?
+                       this.each( doAnimation ) :
+                       this.queue( optall.queue, doAnimation );
+       },
+
+       stop: function( type, clearQueue, gotoEnd ) {
+               if ( typeof type !== "string" ) {
+                       gotoEnd = clearQueue;
+                       clearQueue = type;
+                       type = undefined;
+               }
+               if ( clearQueue && type !== false ) {
+                       this.queue( type || "fx", [] );
+               }
+
+               return this.each(function() {
+                       var index,
+                               hadTimers = false,
+                               timers = jQuery.timers,
+                               data = jQuery._data( this );
+
+                       // clear marker counters if we know they won't be
+                       if ( !gotoEnd ) {
+                               jQuery._unmark( true, this );
+                       }
+
+                       function stopQueue( elem, data, index ) {
+                               var hooks = data[ index ];
+                               jQuery.removeData( elem, index, true );
+                               hooks.stop( gotoEnd );
+                       }
+
+                       if ( type == null ) {
+                               for ( index in data ) {
+                                       if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
+                                               stopQueue( this, data, index );
+                                       }
+                               }
+                       } else if ( data[ index = type + ".run" ] && data[ index ].stop ){
+                               stopQueue( this, data, index );
+                       }
+
+                       for ( index = timers.length; index--; ) {
+                               if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+                                       if ( gotoEnd ) {
+
+                                               // force the next step to be the last
+                                               timers[ index ]( true );
+                                       } else {
+                                               timers[ index ].saveState();
+                                       }
+                                       hadTimers = true;
+                                       timers.splice( index, 1 );
+                               }
+                       }
+
+                       // start the next in the queue if the last step wasn't forced
+                       // timers currently will call their complete callbacks, which will dequeue
+                       // but only if they were gotoEnd
+                       if ( !( gotoEnd && hadTimers ) ) {
+                               jQuery.dequeue( this, type );
+                       }
+               });
+       }
+
+});
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+       setTimeout( clearFxNow, 0 );
+       return ( fxNow = jQuery.now() );
+}
+
+function clearFxNow() {
+       fxNow = undefined;
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, num ) {
+       var obj = {};
+
+       jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice( 0, num )), function() {
+               obj[ this ] = type;
+       });
+
+       return obj;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+       slideDown: genFx( "show", 1 ),
+       slideUp: genFx( "hide", 1 ),
+       slideToggle: genFx( "toggle", 1 ),
+       fadeIn: { opacity: "show" },
+       fadeOut: { opacity: "hide" },
+       fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+       jQuery.fn[ name ] = function( speed, easing, callback ) {
+               return this.animate( props, speed, easing, callback );
+       };
+});
+
+jQuery.extend({
+       speed: function( speed, easing, fn ) {
+               var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+                       complete: fn || !fn && easing ||
+                               jQuery.isFunction( speed ) && speed,
+                       duration: speed,
+                       easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+               };
+
+               opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+                       opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+               // normalize opt.queue - true/undefined/null -> "fx"
+               if ( opt.queue == null || opt.queue === true ) {
+                       opt.queue = "fx";
+               }
+
+               // Queueing
+               opt.old = opt.complete;
+
+               opt.complete = function( noUnmark ) {
+                       if ( jQuery.isFunction( opt.old ) ) {
+                               opt.old.call( this );
+                       }
+
+                       if ( opt.queue ) {
+                               jQuery.dequeue( this, opt.queue );
+                       } else if ( noUnmark !== false ) {
+                               jQuery._unmark( this );
+                       }
+               };
+
+               return opt;
+       },
+
+       easing: {
+               linear: function( p, n, firstNum, diff ) {
+                       return firstNum + diff * p;
+               },
+               swing: function( p, n, firstNum, diff ) {
+                       return ( ( -Math.cos( p*Math.PI ) / 2 ) + 0.5 ) * diff + firstNum;
+               }
+       },
+
+       timers: [],
+
+       fx: function( elem, options, prop ) {
+               this.options = options;
+               this.elem = elem;
+               this.prop = prop;
+
+               options.orig = options.orig || {};
+       }
+
+});
+
+jQuery.fx.prototype = {
+       // Simple function for setting a style value
+       update: function() {
+               if ( this.options.step ) {
+                       this.options.step.call( this.elem, this.now, this );
+               }
+
+               ( jQuery.fx.step[ this.prop ] || jQuery.fx.step._default )( this );
+       },
+
+       // Get the current size
+       cur: function() {
+               if ( this.elem[ this.prop ] != null && (!this.elem.style || this.elem.style[ this.prop ] == null) ) {
+                       return this.elem[ this.prop ];
+               }
+
+               var parsed,
+                       r = jQuery.css( this.elem, this.prop );
+               // Empty strings, null, undefined and "auto" are converted to 0,
+               // complex values such as "rotate(1rad)" are returned as is,
+               // simple values such as "10px" are parsed to Float.
+               return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
+       },
+
+       // Start an animation from one number to another
+       custom: function( from, to, unit ) {
+               var self = this,
+                       fx = jQuery.fx;
+
+               this.startTime = fxNow || createFxNow();
+               this.end = to;
+               this.now = this.start = from;
+               this.pos = this.state = 0;
+               this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
+
+               function t( gotoEnd ) {
+                       return self.step( gotoEnd );
+               }
+
+               t.queue = this.options.queue;
+               t.elem = this.elem;
+               t.saveState = function() {
+                       if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
+                               jQuery._data( self.elem, "fxshow" + self.prop, self.start );
+                       }
+               };
+
+               if ( t() && jQuery.timers.push(t) && !timerId ) {
+                       timerId = setInterval( fx.tick, fx.interval );
+               }
+       },
+
+       // Simple 'show' function
+       show: function() {
+               var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );
+
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[ this.prop ] = dataShow || jQuery.style( this.elem, this.prop );
+               this.options.show = true;
+
+               // Begin the animation
+               // Make sure that we start at a small width/height to avoid any flash of content
+               if ( dataShow !== undefined ) {
+                       // This show is picking up where a previous hide or show left off
+                       this.custom( this.cur(), dataShow );
+               } else {
+                       this.custom( this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur() );
+               }
+
+               // Start by showing the element
+               jQuery( this.elem ).show();
+       },
+
+       // Simple 'hide' function
+       hide: function() {
+               // Remember where we started, so that we can go back to it later
+               this.options.orig[ this.prop ] = jQuery._data( this.elem, "fxshow" + this.prop ) || jQuery.style( this.elem, this.prop );
+               this.options.hide = true;
+
+               // Begin the animation
+               this.custom( this.cur(), 0 );
+       },
+
+       // Each step of an animation
+       step: function( gotoEnd ) {
+               var p, n, complete,
+                       t = fxNow || createFxNow(),
+                       done = true,
+                       elem = this.elem,
+                       options = this.options;
+
+               if ( gotoEnd || t >= options.duration + this.startTime ) {
+                       this.now = this.end;
+                       this.pos = this.state = 1;
+                       this.update();
+
+                       options.animatedProperties[ this.prop ] = true;
+
+                       for ( p in options.animatedProperties ) {
+                               if ( options.animatedProperties[ p ] !== true ) {
+                                       done = false;
+                               }
+                       }
+
+                       if ( done ) {
+                               // Reset the overflow
+                               if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
+
+                                       jQuery.each( [ "", "X", "Y" ], function( index, value ) {
+                                               elem.style[ "overflow" + value ] = options.overflow[ index ];
+                                       });
+                               }
+
+                               // Hide the element if the "hide" operation was done
+                               if ( options.hide ) {
+                                       jQuery( elem ).hide();
+                               }
+
+                               // Reset the properties, if the item has been hidden or shown
+                               if ( options.hide || options.show ) {
+                                       for ( p in options.animatedProperties ) {
+                                               jQuery.style( elem, p, options.orig[ p ] );
+                                               jQuery.removeData( elem, "fxshow" + p, true );
+                                               // Toggle data is no longer needed
+                                               jQuery.removeData( elem, "toggle" + p, true );
+                                       }
+                               }
+
+                               // Execute the complete function
+                               // in the event that the complete function throws an exception
+                               // we must ensure it won't be called twice. #5684
+
+                               complete = options.complete;
+                               if ( complete ) {
+
+                                       options.complete = false;
+                                       complete.call( elem );
+                               }
+                       }
+
+                       return false;
+
+               } else {
+                       // classical easing cannot be used with an Infinity duration
+                       if ( options.duration == Infinity ) {
+                               this.now = t;
+                       } else {
+                               n = t - this.startTime;
+                               this.state = n / options.duration;
+
+                               // Perform the easing function, defaults to swing
+                               this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, options.duration );
+                               this.now = this.start + ( (this.end - this.start) * this.pos );
+                       }
+                       // Perform the next step of the animation
+                       this.update();
+               }
+
+               return true;
+       }
+};
+
+jQuery.extend( jQuery.fx, {
+       tick: function() {
+               var timer,
+                       timers = jQuery.timers,
+                       i = 0;
+
+               for ( ; i < timers.length; i++ ) {
+                       timer = timers[ i ];
+                       // Checks the timer has not already been removed
+                       if ( !timer() && timers[ i ] === timer ) {
+                               timers.splice( i--, 1 );
+                       }
+               }
+
+               if ( !timers.length ) {
+                       jQuery.fx.stop();
+               }
+       },
+
+       interval: 13,
+
+       stop: function() {
+               clearInterval( timerId );
+               timerId = null;
+       },
+
+       speeds: {
+               slow: 600,
+               fast: 200,
+               // Default speed
+               _default: 400
+       },
+
+       step: {
+               opacity: function( fx ) {
+                       jQuery.style( fx.elem, "opacity", fx.now );
+               },
+
+               _default: function( fx ) {
+                       if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
+                               fx.elem.style[ fx.prop ] = fx.now + fx.unit;
+                       } else {
+                               fx.elem[ fx.prop ] = fx.now;
+                       }
+               }
+       }
+});
+
+// Adds width/height step functions
+// Do not set anything below 0
+jQuery.each([ "width", "height" ], function( i, prop ) {
+       jQuery.fx.step[ prop ] = function( fx ) {
+               jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
+       };
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+       jQuery.expr.filters.animated = function( elem ) {
+               return jQuery.grep(jQuery.timers, function( fn ) {
+                       return elem === fn.elem;
+               }).length;
+       };
+}
+
+// Try to restore the default display value of an element
+function defaultDisplay( nodeName ) {
+
+       if ( !elemdisplay[ nodeName ] ) {
+
+               var body = document.body,
+                       elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
+                       display = elem.css( "display" );
+               elem.remove();
+
+               // If the simple way fails,
+               // get element's real default display by attaching it to a temp iframe
+               if ( display === "none" || display === "" ) {
+                       // No iframe to use yet, so create it
+                       if ( !iframe ) {
+                               iframe = document.createElement( "iframe" );
+                               iframe.frameBorder = iframe.width = iframe.height = 0;
+                       }
+
+                       body.appendChild( iframe );
+
+                       // Create a cacheable copy of the iframe document on first call.
+                       // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
+                       // document to it; WebKit & Firefox won't allow reusing the iframe document.
+                       if ( !iframeDoc || !iframe.createElement ) {
+                               iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
+                               iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
+                               iframeDoc.close();
+                       }
+
+                       elem = iframeDoc.createElement( nodeName );
+
+                       iframeDoc.body.appendChild( elem );
+
+                       display = jQuery.css( elem, "display" );
+                       body.removeChild( iframe );
+               }
+
+               // Store the correct default display
+               elemdisplay[ nodeName ] = display;
+       }
+
+       return elemdisplay[ nodeName ];
+}
+
+
+
+
+var rtable = /^t(?:able|d|h)$/i,
+       rroot = /^(?:body|html)$/i;
+
+if ( "getBoundingClientRect" in document.documentElement ) {
+       jQuery.fn.offset = function( options ) {
+               var elem = this[0], box;
+
+               if ( options ) {
+                       return this.each(function( i ) {
+                               jQuery.offset.setOffset( this, options, i );
+                       });
+               }
+
+               if ( !elem || !elem.ownerDocument ) {
+                       return null;
+               }
+
+               if ( elem === elem.ownerDocument.body ) {
+                       return jQuery.offset.bodyOffset( elem );
+               }
+
+               try {
+                       box = elem.getBoundingClientRect();
+               } catch(e) {}
+
+               var doc = elem.ownerDocument,
+                       docElem = doc.documentElement;
+
+               // Make sure we're not dealing with a disconnected DOM node
+               if ( !box || !jQuery.contains( docElem, elem ) ) {
+                       return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
+               }
+
+               var body = doc.body,
+                       win = getWindow(doc),
+                       clientTop  = docElem.clientTop  || body.clientTop  || 0,
+                       clientLeft = docElem.clientLeft || body.clientLeft || 0,
+                       scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
+                       scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
+                       top  = box.top  + scrollTop  - clientTop,
+                       left = box.left + scrollLeft - clientLeft;
+
+               return { top: top, left: left };
+       };
+
+} else {
+       jQuery.fn.offset = function( options ) {
+               var elem = this[0];
+
+               if ( options ) {
+                       return this.each(function( i ) {
+                               jQuery.offset.setOffset( this, options, i );
+                       });
+               }
+
+               if ( !elem || !elem.ownerDocument ) {
+                       return null;
+               }
+
+               if ( elem === elem.ownerDocument.body ) {
+                       return jQuery.offset.bodyOffset( elem );
+               }
+
+               var computedStyle,
+                       offsetParent = elem.offsetParent,
+                       prevOffsetParent = elem,
+                       doc = elem.ownerDocument,
+                       docElem = doc.documentElement,
+                       body = doc.body,
+                       defaultView = doc.defaultView,
+                       prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
+                       top = elem.offsetTop,
+                       left = elem.offsetLeft;
+
+               while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
+                       if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+                               break;
+                       }
+
+                       computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
+                       top  -= elem.scrollTop;
+                       left -= elem.scrollLeft;
+
+                       if ( elem === offsetParent ) {
+                               top  += elem.offsetTop;
+                               left += elem.offsetLeft;
+
+                               if ( jQuery.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
+                                       top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+                                       left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+                               }
+
+                               prevOffsetParent = offsetParent;
+                               offsetParent = elem.offsetParent;
+                       }
+
+                       if ( jQuery.support.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
+                               top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
+                               left += parseFloat( computedStyle.borderLeftWidth ) || 0;
+                       }
+
+                       prevComputedStyle = computedStyle;
+               }
+
+               if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
+                       top  += body.offsetTop;
+                       left += body.offsetLeft;
+               }
+
+               if ( jQuery.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
+                       top  += Math.max( docElem.scrollTop, body.scrollTop );
+                       left += Math.max( docElem.scrollLeft, body.scrollLeft );
+               }
+
+               return { top: top, left: left };
+       };
+}
+
+jQuery.offset = {
+
+       bodyOffset: function( body ) {
+               var top = body.offsetTop,
+                       left = body.offsetLeft;
+
+               if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) {
+                       top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
+                       left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
+               }
+
+               return { top: top, left: left };
+       },
+
+       setOffset: function( elem, options, i ) {
+               var position = jQuery.css( elem, "position" );
+
+               // set position first, in-case top/left are set even on static elem
+               if ( position === "static" ) {
+                       elem.style.position = "relative";
+               }
+
+               var curElem = jQuery( elem ),
+                       curOffset = curElem.offset(),
+                       curCSSTop = jQuery.css( elem, "top" ),
+                       curCSSLeft = jQuery.css( elem, "left" ),
+                       calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
+                       props = {}, curPosition = {}, curTop, curLeft;
+
+               // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+               if ( calculatePosition ) {
+                       curPosition = curElem.position();
+                       curTop = curPosition.top;
+                       curLeft = curPosition.left;
+               } else {
+                       curTop = parseFloat( curCSSTop ) || 0;
+                       curLeft = parseFloat( curCSSLeft ) || 0;
+               }
+
+               if ( jQuery.isFunction( options ) ) {
+                       options = options.call( elem, i, curOffset );
+               }
+
+               if ( options.top != null ) {
+                       props.top = ( options.top - curOffset.top ) + curTop;
+               }
+               if ( options.left != null ) {
+                       props.left = ( options.left - curOffset.left ) + curLeft;
+               }
+
+               if ( "using" in options ) {
+                       options.using.call( elem, props );
+               } else {
+                       curElem.css( props );
+               }
+       }
+};
+
+
+jQuery.fn.extend({
+
+       position: function() {
+               if ( !this[0] ) {
+                       return null;
+               }
+
+               var elem = this[0],
+
+               // Get *real* offsetParent
+               offsetParent = this.offsetParent(),
+
+               // Get correct offsets
+               offset       = this.offset(),
+               parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
+
+               // Subtract element margins
+               // note: when an element has margin: auto the offsetLeft and marginLeft
+               // are the same in Safari causing offset.left to incorrectly be 0
+               offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
+               offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
+
+               // Add offsetParent borders
+               parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
+               parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
+
+               // Subtract the two offsets
+               return {
+                       top:  offset.top  - parentOffset.top,
+                       left: offset.left - parentOffset.left
+               };
+       },
+
+       offsetParent: function() {
+               return this.map(function() {
+                       var offsetParent = this.offsetParent || document.body;
+                       while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
+                               offsetParent = offsetParent.offsetParent;
+                       }
+                       return offsetParent;
+               });
+       }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( ["Left", "Top"], function( i, name ) {
+       var method = "scroll" + name;
+
+       jQuery.fn[ method ] = function( val ) {
+               var elem, win;
+
+               if ( val === undefined ) {
+                       elem = this[ 0 ];
+
+                       if ( !elem ) {
+                               return null;
+                       }
+
+                       win = getWindow( elem );
+
+                       // Return the scroll offset
+                       return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
+                               jQuery.support.boxModel && win.document.documentElement[ method ] ||
+                                       win.document.body[ method ] :
+                               elem[ method ];
+               }
+
+               // Set the scroll offset
+               return this.each(function() {
+                       win = getWindow( this );
+
+                       if ( win ) {
+                               win.scrollTo(
+                                       !i ? val : jQuery( win ).scrollLeft(),
+                                        i ? val : jQuery( win ).scrollTop()
+                               );
+
+                       } else {
+                               this[ method ] = val;
+                       }
+               });
+       };
+});
+
+function getWindow( elem ) {
+       return jQuery.isWindow( elem ) ?
+               elem :
+               elem.nodeType === 9 ?
+                       elem.defaultView || elem.parentWindow :
+                       false;
+}
+
+
+
+
+// Create width, height, innerHeight, innerWidth, outerHeight and outerWidth methods
+jQuery.each([ "Height", "Width" ], function( i, name ) {
+
+       var type = name.toLowerCase();
+
+       // innerHeight and innerWidth
+       jQuery.fn[ "inner" + name ] = function() {
+               var elem = this[0];
+               return elem ?
+                       elem.style ?
+                       parseFloat( jQuery.css( elem, type, "padding" ) ) :
+                       this[ type ]() :
+                       null;
+       };
+
+       // outerHeight and outerWidth
+       jQuery.fn[ "outer" + name ] = function( margin ) {
+               var elem = this[0];
+               return elem ?
+                       elem.style ?
+                       parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
+                       this[ type ]() :
+                       null;
+       };
+
+       jQuery.fn[ type ] = function( size ) {
+               // Get window width or height
+               var elem = this[0];
+               if ( !elem ) {
+                       return size == null ? null : this;
+               }
+
+               if ( jQuery.isFunction( size ) ) {
+                       return this.each(function( i ) {
+                               var self = jQuery( this );
+                               self[ type ]( size.call( this, i, self[ type ]() ) );
+                       });
+               }
+
+               if ( jQuery.isWindow( elem ) ) {
+                       // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
+                       // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
+                       var docElemProp = elem.document.documentElement[ "client" + name ],
+                               body = elem.document.body;
+                       return elem.document.compatMode === "CSS1Compat" && docElemProp ||
+                               body && body[ "client" + name ] || docElemProp;
+
+               // Get document width or height
+               } else if ( elem.nodeType === 9 ) {
+                       // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
+                       return Math.max(
+                               elem.documentElement["client" + name],
+                               elem.body["scroll" + name], elem.documentElement["scroll" + name],
+                               elem.body["offset" + name], elem.documentElement["offset" + name]
+                       );
+
+               // Get or set width or height on the element
+               } else if ( size === undefined ) {
+                       var orig = jQuery.css( elem, type ),
+                               ret = parseFloat( orig );
+
+                       return jQuery.isNumeric( ret ) ? ret : orig;
+
+               // Set the width or height on the element (default to pixels if value is unitless)
+               } else {
+                       return this.css( type, typeof size === "string" ? size : size + "px" );
+               }
+       };
+
+});
+
+
+
+
+// Expose jQuery to the global object
+window.jQuery = window.$ = jQuery;
+
+// Expose jQuery as an AMD module, but only for AMD loaders that
+// understand the issues with loading multiple versions of jQuery
+// in a page that all might call define(). The loader will indicate
+// they have special allowances for multiple jQuery versions by
+// specifying define.amd.jQuery = true. Register as a named module,
+// since jQuery can be concatenated with other files that may use define,
+// but not use a proper concatenation script that understands anonymous
+// AMD modules. A named AMD is safest and most robust way to register.
+// Lowercase jquery is used because AMD module names are derived from
+// file names, and jQuery is normally delivered in a lowercase file name.
+// Do this after creating the global so that if an AMD module wants to call
+// noConflict to hide this version of jQuery, it will work.
+if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
+       define( "jquery", [], function () { return jQuery; } );
+}
+
+
+
+})( window );
diff --git a/html/_static/link_icon.png b/html/_static/link_icon.png
new file mode 100644 (file)
index 0000000..824a179
Binary files /dev/null and b/html/_static/link_icon.png differ
diff --git a/html/_static/logo_bg.png b/html/_static/logo_bg.png
new file mode 100644 (file)
index 0000000..49708ca
Binary files /dev/null and b/html/_static/logo_bg.png differ
diff --git a/html/_static/logo_full.png b/html/_static/logo_full.png
new file mode 100644 (file)
index 0000000..e003c02
Binary files /dev/null and b/html/_static/logo_full.png differ
diff --git a/html/_static/logo_icon.png b/html/_static/logo_icon.png
new file mode 100644 (file)
index 0000000..eb1bf16
Binary files /dev/null and b/html/_static/logo_icon.png differ
diff --git a/html/_static/logo_nav.png b/html/_static/logo_nav.png
new file mode 100644 (file)
index 0000000..7086584
Binary files /dev/null and b/html/_static/logo_nav.png differ
diff --git a/html/_static/logo_reddit.png b/html/_static/logo_reddit.png
new file mode 100644 (file)
index 0000000..75d46ed
Binary files /dev/null and b/html/_static/logo_reddit.png differ
diff --git a/html/_static/minus.png b/html/_static/minus.png
new file mode 100644 (file)
index 0000000..da1c562
Binary files /dev/null and b/html/_static/minus.png differ
diff --git a/html/_static/myface.png b/html/_static/myface.png
new file mode 100644 (file)
index 0000000..1465459
Binary files /dev/null and b/html/_static/myface.png differ
diff --git a/html/_static/myface_small.png b/html/_static/myface_small.png
new file mode 100644 (file)
index 0000000..24314f6
Binary files /dev/null and b/html/_static/myface_small.png differ
diff --git a/html/_static/paypal.png b/html/_static/paypal.png
new file mode 100644 (file)
index 0000000..5e93685
Binary files /dev/null and b/html/_static/paypal.png differ
diff --git a/html/_static/plus.png b/html/_static/plus.png
new file mode 100644 (file)
index 0000000..b3cb374
Binary files /dev/null and b/html/_static/plus.png differ
diff --git a/html/_static/pygments.css b/html/_static/pygments.css
new file mode 100644 (file)
index 0000000..1a14f2a
--- /dev/null
@@ -0,0 +1,62 @@
+.highlight .hll { background-color: #ffffcc }
+.highlight  { background: #eeffcc; }
+.highlight .c { color: #408090; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #007020; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #007020 } /* Comment.Preproc */
+.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #303030 } /* Generic.Output */
+.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0040D0 } /* Generic.Traceback */
+.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #007020 } /* Keyword.Pseudo */
+.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #902000 } /* Keyword.Type */
+.highlight .m { color: #208050 } /* Literal.Number */
+.highlight .s { color: #4070a0 } /* Literal.String */
+.highlight .na { color: #4070a0 } /* Name.Attribute */
+.highlight .nb { color: #007020 } /* Name.Builtin */
+.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.highlight .no { color: #60add5 } /* Name.Constant */
+.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #007020 } /* Name.Exception */
+.highlight .nf { color: #06287e } /* Name.Function */
+.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
+.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #bb60d5 } /* Name.Variable */
+.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mf { color: #208050 } /* Literal.Number.Float */
+.highlight .mh { color: #208050 } /* Literal.Number.Hex */
+.highlight .mi { color: #208050 } /* Literal.Number.Integer */
+.highlight .mo { color: #208050 } /* Literal.Number.Oct */
+.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
+.highlight .sc { color: #4070a0 } /* Literal.String.Char */
+.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
+.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
+.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.highlight .sx { color: #c65d09 } /* Literal.String.Other */
+.highlight .sr { color: #235388 } /* Literal.String.Regex */
+.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
+.highlight .ss { color: #517918 } /* Literal.String.Symbol */
+.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
+.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
+.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
+.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
\ No newline at end of file
diff --git a/html/_static/searchtools.js b/html/_static/searchtools.js
new file mode 100644 (file)
index 0000000..663be4c
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * searchtools.js_t
+ * ~~~~~~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilties for the full-text search.
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * helper function to return a node containing the
+ * search summary for a given text. keywords is a list
+ * of stemmed words, hlwords is the list of normal, unstemmed
+ * words. the first one is used to find the occurance, the
+ * latter for highlighting it.
+ */
+
+jQuery.makeSearchSummary = function(text, keywords, hlwords) {
+  var textLower = text.toLowerCase();
+  var start = 0;
+  $.each(keywords, function() {
+    var i = textLower.indexOf(this.toLowerCase());
+    if (i > -1)
+      start = i;
+  });
+  start = Math.max(start - 120, 0);
+  var excerpt = ((start > 0) ? '...' : '') +
+  $.trim(text.substr(start, 240)) +
+  ((start + 240 - text.length) ? '...' : '');
+  var rv = $('<div class="context"></div>').text(excerpt);
+  $.each(hlwords, function() {
+    rv = rv.highlightText(this, 'highlighted');
+  });
+  return rv;
+}
+
+
+/**
+ * Porter Stemmer
+ */
+var Stemmer = function() {
+
+  var step2list = {
+    ational: 'ate',
+    tional: 'tion',
+    enci: 'ence',
+    anci: 'ance',
+    izer: 'ize',
+    bli: 'ble',
+    alli: 'al',
+    entli: 'ent',
+    eli: 'e',
+    ousli: 'ous',
+    ization: 'ize',
+    ation: 'ate',
+    ator: 'ate',
+    alism: 'al',
+    iveness: 'ive',
+    fulness: 'ful',
+    ousness: 'ous',
+    aliti: 'al',
+    iviti: 'ive',
+    biliti: 'ble',
+    logi: 'log'
+  };
+
+  var step3list = {
+    icate: 'ic',
+    ative: '',
+    alize: 'al',
+    iciti: 'ic',
+    ical: 'ic',
+    ful: '',
+    ness: ''
+  };
+
+  var c = "[^aeiou]";          // consonant
+  var v = "[aeiouy]";          // vowel
+  var C = c + "[^aeiouy]*";    // consonant sequence
+  var V = v + "[aeiou]*";      // vowel sequence
+
+  var mgr0 = "^(" + C + ")?" + V + C;                      // [C]VC... is m>0
+  var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$";    // [C]VC[V] is m=1
+  var mgr1 = "^(" + C + ")?" + V + C + V + C;              // [C]VCVC... is m>1
+  var s_v   = "^(" + C + ")?" + v;                         // vowel in stem
+
+  this.stemWord = function (w) {
+    var stem;
+    var suffix;
+    var firstch;
+    var origword = w;
+
+    if (w.length < 3)
+      return w;
+
+    var re;
+    var re2;
+    var re3;
+    var re4;
+
+    firstch = w.substr(0,1);
+    if (firstch == "y")
+      w = firstch.toUpperCase() + w.substr(1);
+
+    // Step 1a
+    re = /^(.+?)(ss|i)es$/;
+    re2 = /^(.+?)([^s])s$/;
+
+    if (re.test(w))
+      w = w.replace(re,"$1$2");
+    else if (re2.test(w))
+      w = w.replace(re2,"$1$2");
+
+    // Step 1b
+    re = /^(.+?)eed$/;
+    re2 = /^(.+?)(ed|ing)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      re = new RegExp(mgr0);
+      if (re.test(fp[1])) {
+        re = /.$/;
+        w = w.replace(re,"");
+      }
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1];
+      re2 = new RegExp(s_v);
+      if (re2.test(stem)) {
+        w = stem;
+        re2 = /(at|bl|iz)$/;
+        re3 = new RegExp("([^aeiouylsz])\\1$");
+        re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+        if (re2.test(w))
+          w = w + "e";
+        else if (re3.test(w)) {
+          re = /.$/;
+          w = w.replace(re,"");
+        }
+        else if (re4.test(w))
+          w = w + "e";
+      }
+    }
+
+    // Step 1c
+    re = /^(.+?)y$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(s_v);
+      if (re.test(stem))
+        w = stem + "i";
+    }
+
+    // Step 2
+    re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step2list[suffix];
+    }
+
+    // Step 3
+    re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step3list[suffix];
+    }
+
+    // Step 4
+    re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+    re2 = /^(.+?)(s|t)(ion)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      if (re.test(stem))
+        w = stem;
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1] + fp[2];
+      re2 = new RegExp(mgr1);
+      if (re2.test(stem))
+        w = stem;
+    }
+
+    // Step 5
+    re = /^(.+?)e$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      re2 = new RegExp(meq1);
+      re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+      if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
+        w = stem;
+    }
+    re = /ll$/;
+    re2 = new RegExp(mgr1);
+    if (re.test(w) && re2.test(w)) {
+      re = /.$/;
+      w = w.replace(re,"");
+    }
+
+    // and turn initial Y back to y
+    if (firstch == "y")
+      w = firstch.toLowerCase() + w.substr(1);
+    return w;
+  }
+}
+
+
+/**
+ * Search Module
+ */
+var Search = {
+
+  _index : null,
+  _queued_query : null,
+  _pulse_status : -1,
+
+  init : function() {
+      var params = $.getQueryParameters();
+      if (params.q) {
+          var query = params.q[0];
+          $('input[name="q"]')[0].value = query;
+          this.performSearch(query);
+      }
+  },
+
+  loadIndex : function(url) {
+    $.ajax({type: "GET", url: url, data: null, success: null,
+            dataType: "script", cache: true});
+  },
+
+  setIndex : function(index) {
+    var q;
+    this._index = index;
+    if ((q = this._queued_query) !== null) {
+      this._queued_query = null;
+      Search.query(q);
+    }
+  },
+
+  hasIndex : function() {
+      return this._index !== null;
+  },
+
+  deferQuery : function(query) {
+      this._queued_query = query;
+  },
+
+  stopPulse : function() {
+      this._pulse_status = 0;
+  },
+
+  startPulse : function() {
+    if (this._pulse_status >= 0)
+        return;
+    function pulse() {
+      Search._pulse_status = (Search._pulse_status + 1) % 4;
+      var dotString = '';
+      for (var i = 0; i < Search._pulse_status; i++)
+        dotString += '.';
+      Search.dots.text(dotString);
+      if (Search._pulse_status > -1)
+        window.setTimeout(pulse, 500);
+    };
+    pulse();
+  },
+
+  /**
+   * perform a search for something
+   */
+  performSearch : function(query) {
+    // create the required interface elements
+    this.out = $('#search-results');
+    this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
+    this.dots = $('<span></span>').appendTo(this.title);
+    this.status = $('<p style="display: none"></p>').appendTo(this.out);
+    this.output = $('<ul class="search"/>').appendTo(this.out);
+
+    $('#search-progress').text(_('Preparing search...'));
+    this.startPulse();
+
+    // index already loaded, the browser was quick!
+    if (this.hasIndex())
+      this.query(query);
+    else
+      this.deferQuery(query);
+  },
+
+  query : function(query) {
+    var stopwords = ["and","then","into","it","as","are","in","if","for","no","there","their","was","is","be","to","that","but","they","not","such","with","by","a","on","these","of","will","this","near","the","or","at"];
+
+    // Stem the searchterms and add them to the correct list
+    var stemmer = new Stemmer();
+    var searchterms = [];
+    var excluded = [];
+    var hlterms = [];
+    var tmp = query.split(/\s+/);
+    var objectterms = [];
+    for (var i = 0; i < tmp.length; i++) {
+      if (tmp[i] != "") {
+          objectterms.push(tmp[i].toLowerCase());
+      }
+
+      if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
+          tmp[i] == "") {
+        // skip this "word"
+        continue;
+      }
+      // stem the word
+      var word = stemmer.stemWord(tmp[i]).toLowerCase();
+      // select the correct list
+      if (word[0] == '-') {
+        var toAppend = excluded;
+        word = word.substr(1);
+      }
+      else {
+        var toAppend = searchterms;
+        hlterms.push(tmp[i].toLowerCase());
+      }
+      // only add if not already in the list
+      if (!$.contains(toAppend, word))
+        toAppend.push(word);
+    };
+    var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
+
+    // console.debug('SEARCH: searching for:');
+    // console.info('required: ', searchterms);
+    // console.info('excluded: ', excluded);
+
+    // prepare search
+    var filenames = this._index.filenames;
+    var titles = this._index.titles;
+    var terms = this._index.terms;
+    var fileMap = {};
+    var files = null;
+    // different result priorities
+    var importantResults = [];
+    var objectResults = [];
+    var regularResults = [];
+    var unimportantResults = [];
+    $('#search-progress').empty();
+
+    // lookup as object
+    for (var i = 0; i < objectterms.length; i++) {
+      var others = [].concat(objectterms.slice(0,i),
+                             objectterms.slice(i+1, objectterms.length))
+      var results = this.performObjectSearch(objectterms[i], others);
+      // Assume first word is most likely to be the object,
+      // other words more likely to be in description.
+      // Therefore put matches for earlier words first.
+      // (Results are eventually used in reverse order).
+      objectResults = results[0].concat(objectResults);
+      importantResults = results[1].concat(importantResults);
+      unimportantResults = results[2].concat(unimportantResults);
+    }
+
+    // perform the search on the required terms
+    for (var i = 0; i < searchterms.length; i++) {
+      var word = searchterms[i];
+      // no match but word was a required one
+      if ((files = terms[word]) == null)
+        break;
+      if (files.length == undefined) {
+        files = [files];
+      }
+      // create the mapping
+      for (var j = 0; j < files.length; j++) {
+        var file = files[j];
+        if (file in fileMap)
+          fileMap[file].push(word);
+        else
+          fileMap[file] = [word];
+      }
+    }
+
+    // now check if the files don't contain excluded terms
+    for (var file in fileMap) {
+      var valid = true;
+
+      // check if all requirements are matched
+      if (fileMap[file].length != searchterms.length)
+        continue;
+
+      // ensure that none of the excluded terms is in the
+      // search result.
+      for (var i = 0; i < excluded.length; i++) {
+        if (terms[excluded[i]] == file ||
+            $.contains(terms[excluded[i]] || [], file)) {
+          valid = false;
+          break;
+        }
+      }
+
+      // if we have still a valid result we can add it
+      // to the result list
+      if (valid)
+        regularResults.push([filenames[file], titles[file], '', null]);
+    }
+
+    // delete unused variables in order to not waste
+    // memory until list is retrieved completely
+    delete filenames, titles, terms;
+
+    // now sort the regular results descending by title
+    regularResults.sort(function(a, b) {
+      var left = a[1].toLowerCase();
+      var right = b[1].toLowerCase();
+      return (left > right) ? -1 : ((left < right) ? 1 : 0);
+    });
+
+    // combine all results
+    var results = unimportantResults.concat(regularResults)
+      .concat(objectResults).concat(importantResults);
+
+    // print the results
+    var resultCount = results.length;
+    function displayNextItem() {
+      // results left, load the summary and display it
+      if (results.length) {
+        var item = results.pop();
+        var listItem = $('<li style="display:none"></li>');
+        if (DOCUMENTATION_OPTIONS.FILE_SUFFIX == '') {
+          // dirhtml builder
+          var dirname = item[0] + '/';
+          if (dirname.match(/\/index\/$/)) {
+            dirname = dirname.substring(0, dirname.length-6);
+          } else if (dirname == 'index/') {
+            dirname = '';
+          }
+          listItem.append($('<a/>').attr('href',
+            DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
+            highlightstring + item[2]).html(item[1]));
+        } else {
+          // normal html builders
+          listItem.append($('<a/>').attr('href',
+            item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
+            highlightstring + item[2]).html(item[1]));
+        }
+        if (item[3]) {
+          listItem.append($('<span> (' + item[3] + ')</span>'));
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
+        } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
+          $.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
+                item[0] + '.txt', function(data) {
+            if (data != '') {
+              listItem.append($.makeSearchSummary(data, searchterms, hlterms));
+              Search.output.append(listItem);
+            }
+            listItem.slideDown(5, function() {
+              displayNextItem();
+            });
+          }, "text");
+        } else {
+          // no source available, just display title
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
+        }
+      }
+      // search finished, update title and status message
+      else {
+        Search.stopPulse();
+        Search.title.text(_('Search Results'));
+        if (!resultCount)
+          Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
+        else
+            Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
+        Search.status.fadeIn(500);
+      }
+    }
+    displayNextItem();
+  },
+
+  performObjectSearch : function(object, otherterms) {
+    var filenames = this._index.filenames;
+    var objects = this._index.objects;
+    var objnames = this._index.objnames;
+    var titles = this._index.titles;
+
+    var importantResults = [];
+    var objectResults = [];
+    var unimportantResults = [];
+
+    for (var prefix in objects) {
+      for (var name in objects[prefix]) {
+        var fullname = (prefix ? prefix + '.' : '') + name;
+        if (fullname.toLowerCase().indexOf(object) > -1) {
+          var match = objects[prefix][name];
+          var objname = objnames[match[1]][2];
+          var title = titles[match[0]];
+          // If more than one term searched for, we require other words to be
+          // found in the name/title/description
+          if (otherterms.length > 0) {
+            var haystack = (prefix + ' ' + name + ' ' +
+                            objname + ' ' + title).toLowerCase();
+            var allfound = true;
+            for (var i = 0; i < otherterms.length; i++) {
+              if (haystack.indexOf(otherterms[i]) == -1) {
+                allfound = false;
+                break;
+              }
+            }
+            if (!allfound) {
+              continue;
+            }
+          }
+          var descr = objname + _(', in ') + title;
+          anchor = match[3];
+          if (anchor == '')
+            anchor = fullname;
+          else if (anchor == '-')
+            anchor = objnames[match[1]][1] + '-' + fullname;
+          result = [filenames[match[0]], fullname, '#'+anchor, descr];
+          switch (match[2]) {
+          case 1: objectResults.push(result); break;
+          case 0: importantResults.push(result); break;
+          case 2: unimportantResults.push(result); break;
+          }
+        }
+      }
+    }
+
+    // sort results descending
+    objectResults.sort(function(a, b) {
+      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+    });
+
+    importantResults.sort(function(a, b) {
+      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+    });
+
+    unimportantResults.sort(function(a, b) {
+      return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
+    });
+
+    return [importantResults, objectResults, unimportantResults]
+  }
+}
+
+$(document).ready(function() {
+  Search.init();
+});
\ No newline at end of file
diff --git a/html/_static/sidebar.js b/html/_static/sidebar.js
new file mode 100644 (file)
index 0000000..a45e192
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * sidebar.js
+ * ~~~~~~~~~~
+ *
+ * This script makes the Sphinx sidebar collapsible.
+ *
+ * .sphinxsidebar contains .sphinxsidebarwrapper.  This script adds
+ * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
+ * used to collapse and expand the sidebar.
+ *
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
+ * and the width of the sidebar and the margin-left of the document
+ * are decreased. When the sidebar is expanded the opposite happens.
+ * This script saves a per-browser/per-session cookie used to
+ * remember the position of the sidebar among the pages.
+ * Once the browser is closed the cookie is deleted and the position
+ * reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+$(function() {
+  // global elements used by the functions.
+  // the 'sidebarbutton' element is defined as global after its
+  // creation, in the add_sidebar_button function
+  var bodywrapper = $('.bodywrapper');
+  var sidebar = $('.sphinxsidebar');
+  var sidebarwrapper = $('.sphinxsidebarwrapper');
+
+  // for some reason, the document has no sidebar; do not run into errors
+  if (!sidebar.length) return;
+
+  // original margin-left of the bodywrapper and width of the sidebar
+  // with the sidebar expanded
+  var bw_margin_expanded = bodywrapper.css('margin-left');
+  var ssb_width_expanded = sidebar.width();
+
+  // margin-left of the bodywrapper and width of the sidebar
+  // with the sidebar collapsed
+  var bw_margin_collapsed = '.8em';
+  var ssb_width_collapsed = '.8em';
+
+  // colors used by the current theme
+  var dark_color = $('.related').css('background-color');
+  var light_color = $('.document').css('background-color');
+
+  function sidebar_is_collapsed() {
+    return sidebarwrapper.is(':not(:visible)');
+  }
+
+  function toggle_sidebar() {
+    if (sidebar_is_collapsed())
+      expand_sidebar();
+    else
+      collapse_sidebar();
+  }
+
+  function collapse_sidebar() {
+    sidebarwrapper.hide();
+    sidebar.css('width', ssb_width_collapsed);
+    bodywrapper.css('margin-left', bw_margin_collapsed);
+    sidebarbutton.css({
+        'margin-left': '0',
+        'height': bodywrapper.height()
+    });
+    sidebarbutton.find('span').text('»');
+    sidebarbutton.attr('title', _('Expand sidebar'));
+    document.cookie = 'sidebar=collapsed';
+  }
+
+  function expand_sidebar() {
+    bodywrapper.css('margin-left', bw_margin_expanded);
+    sidebar.css('width', ssb_width_expanded);
+    sidebarwrapper.show();
+    sidebarbutton.css({
+        'margin-left': ssb_width_expanded-12,
+        'height': bodywrapper.height()
+    });
+    sidebarbutton.find('span').text('«');
+    sidebarbutton.attr('title', _('Collapse sidebar'));
+    document.cookie = 'sidebar=expanded';
+  }
+
+  function add_sidebar_button() {
+    sidebarwrapper.css({
+        'float': 'left',
+        'margin-right': '0',
+        'width': ssb_width_expanded - 28
+    });
+    // create the button
+    sidebar.append(
+        '<div id="sidebarbutton"><span>&laquo;</span></div>'
+    );
+    var sidebarbutton = $('#sidebarbutton');
+    light_color = sidebarbutton.css('background-color');
+    // find the height of the viewport to center the '<<' in the page
+    var viewport_height;
+    if (window.innerHeight)
+         viewport_height = window.innerHeight;
+    else
+         viewport_height = $(window).height();
+    sidebarbutton.find('span').css({
+        'display': 'block',
+        'margin-top': (viewport_height - sidebar.position().top - 20) / 2
+    });
+
+    sidebarbutton.click(toggle_sidebar);
+    sidebarbutton.attr('title', _('Collapse sidebar'));
+    sidebarbutton.css({
+        'color': '#FFFFFF',
+        'border-left': '1px solid ' + dark_color,
+        'font-size': '1.2em',
+        'cursor': 'pointer',
+        'height': bodywrapper.height(),
+        'padding-top': '1px',
+        'margin-left': ssb_width_expanded - 12
+    });
+
+    sidebarbutton.hover(
+      function () {
+          $(this).css('background-color', dark_color);
+      },
+      function () {
+          $(this).css('background-color', light_color);
+      }
+    );
+  }
+
+  function set_position_from_cookie() {
+    if (!document.cookie)
+      return;
+    var items = document.cookie.split(';');
+    for(var k=0; k<items.length; k++) {
+      var key_val = items[k].split('=');
+      var key = key_val[0];
+      if (key == 'sidebar') {
+        var value = key_val[1];
+        if ((value == 'collapsed') && (!sidebar_is_collapsed()))
+          collapse_sidebar();
+        else if ((value == 'expanded') && (sidebar_is_collapsed()))
+          expand_sidebar();
+      }
+    }
+  }
+
+  add_sidebar_button();
+  var sidebarbutton = $('#sidebarbutton');
+  set_position_from_cookie();
+});
diff --git a/html/_static/underscore.js b/html/_static/underscore.js
new file mode 100644 (file)
index 0000000..eaba008
--- /dev/null
@@ -0,0 +1,807 @@
+//     Underscore.js 1.1.6
+//     (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
+//     Underscore is freely distributable under the MIT license.
+//     Portions of Underscore are inspired or borrowed from Prototype,
+//     Oliver Steele's Functional, and John Resig's Micro-Templating.
+//     For all details and documentation:
+//     http://documentcloud.github.com/underscore
+
+(function() {
+
+  // Baseline setup
+  // --------------
+
+  // Establish the root object, `window` in the browser, or `global` on the server.
+  var root = this;
+
+  // Save the previous value of the `_` variable.
+  var previousUnderscore = root._;
+
+  // Establish the object that gets returned to break out of a loop iteration.
+  var breaker = {};
+
+  // Save bytes in the minified (but not gzipped) version:
+  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
+
+  // Create quick reference variables for speed access to core prototypes.
+  var slice            = ArrayProto.slice,
+      unshift          = ArrayProto.unshift,
+      toString         = ObjProto.toString,
+      hasOwnProperty   = ObjProto.hasOwnProperty;
+
+  // All **ECMAScript 5** native function implementations that we hope to use
+  // are declared here.
+  var
+    nativeForEach      = ArrayProto.forEach,
+    nativeMap          = ArrayProto.map,
+    nativeReduce       = ArrayProto.reduce,
+    nativeReduceRight  = ArrayProto.reduceRight,
+    nativeFilter       = ArrayProto.filter,
+    nativeEvery        = ArrayProto.every,
+    nativeSome         = ArrayProto.some,
+    nativeIndexOf      = ArrayProto.indexOf,
+    nativeLastIndexOf  = ArrayProto.lastIndexOf,
+    nativeIsArray      = Array.isArray,
+    nativeKeys         = Object.keys,
+    nativeBind         = FuncProto.bind;
+
+  // Create a safe reference to the Underscore object for use below.
+  var _ = function(obj) { return new wrapper(obj); };
+
+  // Export the Underscore object for **CommonJS**, with backwards-compatibility
+  // for the old `require()` API. If we're not in CommonJS, add `_` to the
+  // global object.
+  if (typeof module !== 'undefined' && module.exports) {
+    module.exports = _;
+    _._ = _;
+  } else {
+    root._ = _;
+  }
+
+  // Current version.
+  _.VERSION = '1.1.6';
+
+  // Collection Functions
+  // --------------------
+
+  // The cornerstone, an `each` implementation, aka `forEach`.
+  // Handles objects implementing `forEach`, arrays, and raw objects.
+  // Delegates to **ECMAScript 5**'s native `forEach` if available.
+  var each = _.each = _.forEach = function(obj, iterator, context) {
+    if (obj == null) return;
+    if (nativeForEach && obj.forEach === nativeForEach) {
+      obj.forEach(iterator, context);
+    } else if (_.isNumber(obj.length)) {
+      for (var i = 0, l = obj.length; i < l; i++) {
+        if (iterator.call(context, obj[i], i, obj) === breaker) return;
+      }
+    } else {
+      for (var key in obj) {
+        if (hasOwnProperty.call(obj, key)) {
+          if (iterator.call(context, obj[key], key, obj) === breaker) return;
+        }
+      }
+    }
+  };
+
+  // Return the results of applying the iterator to each element.
+  // Delegates to **ECMAScript 5**'s native `map` if available.
+  _.map = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
+    each(obj, function(value, index, list) {
+      results[results.length] = iterator.call(context, value, index, list);
+    });
+    return results;
+  };
+
+  // **Reduce** builds up a single result from a list of values, aka `inject`,
+  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
+  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
+    var initial = memo !== void 0;
+    if (obj == null) obj = [];
+    if (nativeReduce && obj.reduce === nativeReduce) {
+      if (context) iterator = _.bind(iterator, context);
+      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
+    }
+    each(obj, function(value, index, list) {
+      if (!initial && index === 0) {
+        memo = value;
+        initial = true;
+      } else {
+        memo = iterator.call(context, memo, value, index, list);
+      }
+    });
+    if (!initial) throw new TypeError("Reduce of empty array with no initial value");
+    return memo;
+  };
+
+  // The right-associative version of reduce, also known as `foldr`.
+  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
+  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
+    if (obj == null) obj = [];
+    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
+      if (context) iterator = _.bind(iterator, context);
+      return memo !== void 0 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+    }
+    var reversed = (_.isArray(obj) ? obj.slice() : _.toArray(obj)).reverse();
+    return _.reduce(reversed, iterator, memo, context);
+  };
+
+  // Return the first value which passes a truth test. Aliased as `detect`.
+  _.find = _.detect = function(obj, iterator, context) {
+    var result;
+    any(obj, function(value, index, list) {
+      if (iterator.call(context, value, index, list)) {
+        result = value;
+        return true;
+      }
+    });
+    return result;
+  };
+
+  // Return all the elements that pass a truth test.
+  // Delegates to **ECMAScript 5**'s native `filter` if available.
+  // Aliased as `select`.
+  _.filter = _.select = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
+    each(obj, function(value, index, list) {
+      if (iterator.call(context, value, index, list)) results[results.length] = value;
+    });
+    return results;
+  };
+
+  // Return all the elements for which a truth test fails.
+  _.reject = function(obj, iterator, context) {
+    var results = [];
+    if (obj == null) return results;
+    each(obj, function(value, index, list) {
+      if (!iterator.call(context, value, index, list)) results[results.length] = value;
+    });
+    return results;
+  };
+
+  // Determine whether all of the elements match a truth test.
+  // Delegates to **ECMAScript 5**'s native `every` if available.
+  // Aliased as `all`.
+  _.every = _.all = function(obj, iterator, context) {
+    var result = true;
+    if (obj == null) return result;
+    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
+    each(obj, function(value, index, list) {
+      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
+    });
+    return result;
+  };
+
+  // Determine if at least one element in the object matches a truth test.
+  // Delegates to **ECMAScript 5**'s native `some` if available.
+  // Aliased as `any`.
+  var any = _.some = _.any = function(obj, iterator, context) {
+    iterator || (iterator = _.identity);
+    var result = false;
+    if (obj == null) return result;
+    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
+    each(obj, function(value, index, list) {
+      if (result = iterator.call(context, value, index, list)) return breaker;
+    });
+    return result;
+  };
+
+  // Determine if a given value is included in the array or object using `===`.
+  // Aliased as `contains`.
+  _.include = _.contains = function(obj, target) {
+    var found = false;
+    if (obj == null) return found;
+    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
+    any(obj, function(value) {
+      if (found = value === target) return true;
+    });
+    return found;
+  };
+
+  // Invoke a method (with arguments) on every item in a collection.
+  _.invoke = function(obj, method) {
+    var args = slice.call(arguments, 2);
+    return _.map(obj, function(value) {
+      return (method.call ? method || value : value[method]).apply(value, args);
+    });
+  };
+
+  // Convenience version of a common use case of `map`: fetching a property.
+  _.pluck = function(obj, key) {
+    return _.map(obj, function(value){ return value[key]; });
+  };
+
+  // Return the maximum element or (element-based computation).
+  _.max = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
+    var result = {computed : -Infinity};
+    each(obj, function(value, index, list) {
+      var computed = iterator ? iterator.call(context, value, index, list) : value;
+      computed >= result.computed && (result = {value : value, computed : computed});
+    });
+    return result.value;
+  };
+
+  // Return the minimum element (or element-based computation).
+  _.min = function(obj, iterator, context) {
+    if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
+    var result = {computed : Infinity};
+    each(obj, function(value, index, list) {
+      var computed = iterator ? iterator.call(context, value, index, list) : value;
+      computed < result.computed && (result = {value : value, computed : computed});
+    });
+    return result.value;
+  };
+
+  // Sort the object's values by a criterion produced by an iterator.
+  _.sortBy = function(obj, iterator, context) {
+    return _.pluck(_.map(obj, function(value, index, list) {
+      return {
+        value : value,
+        criteria : iterator.call(context, value, index, list)
+      };
+    }).sort(function(left, right) {
+      var a = left.criteria, b = right.criteria;
+      return a < b ? -1 : a > b ? 1 : 0;
+    }), 'value');
+  };
+
+  // Use a comparator function to figure out at what index an object should
+  // be inserted so as to maintain order. Uses binary search.
+  _.sortedIndex = function(array, obj, iterator) {
+    iterator || (iterator = _.identity);
+    var low = 0, high = array.length;
+    while (low < high) {
+      var mid = (low + high) >> 1;
+      iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
+    }
+    return low;
+  };
+
+  // Safely convert anything iterable into a real, live array.
+  _.toArray = function(iterable) {
+    if (!iterable)                return [];
+    if (iterable.toArray)         return iterable.toArray();
+    if (_.isArray(iterable))      return iterable;
+    if (_.isArguments(iterable))  return slice.call(iterable);
+    return _.values(iterable);
+  };
+
+  // Return the number of elements in an object.
+  _.size = function(obj) {
+    return _.toArray(obj).length;
+  };
+
+  // Array Functions
+  // ---------------
+
+  // Get the first element of an array. Passing **n** will return the first N
+  // values in the array. Aliased as `head`. The **guard** check allows it to work
+  // with `_.map`.
+  _.first = _.head = function(array, n, guard) {
+    return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
+  };
+
+  // Returns everything but the first entry of the array. Aliased as `tail`.
+  // Especially useful on the arguments object. Passing an **index** will return
+  // the rest of the values in the array from that index onward. The **guard**
+  // check allows it to work with `_.map`.
+  _.rest = _.tail = function(array, index, guard) {
+    return slice.call(array, (index == null) || guard ? 1 : index);
+  };
+
+  // Get the last element of an array.
+  _.last = function(array) {
+    return array[array.length - 1];
+  };
+
+  // Trim out all falsy values from an array.
+  _.compact = function(array) {
+    return _.filter(array, function(value){ return !!value; });
+  };
+
+  // Return a completely flattened version of an array.
+  _.flatten = function(array) {
+    return _.reduce(array, function(memo, value) {
+      if (_.isArray(value)) return memo.concat(_.flatten(value));
+      memo[memo.length] = value;
+      return memo;
+    }, []);
+  };
+
+  // Return a version of the array that does not contain the specified value(s).
+  _.without = function(array) {
+    var values = slice.call(arguments, 1);
+    return _.filter(array, function(value){ return !_.include(values, value); });
+  };
+
+  // Produce a duplicate-free version of the array. If the array has already
+  // been sorted, you have the option of using a faster algorithm.
+  // Aliased as `unique`.
+  _.uniq = _.unique = function(array, isSorted) {
+    return _.reduce(array, function(memo, el, i) {
+      if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo[memo.length] = el;
+      return memo;
+    }, []);
+  };
+
+  // Produce an array that contains every item shared between all the
+  // passed-in arrays.
+  _.intersect = function(array) {
+    var rest = slice.call(arguments, 1);
+    return _.filter(_.uniq(array), function(item) {
+      return _.every(rest, function(other) {
+        return _.indexOf(other, item) >= 0;
+      });
+    });
+  };
+
+  // Zip together multiple lists into a single array -- elements that share
+  // an index go together.
+  _.zip = function() {
+    var args = slice.call(arguments);
+    var length = _.max(_.pluck(args, 'length'));
+    var results = new Array(length);
+    for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
+    return results;
+  };
+
+  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
+  // we need this function. Return the position of the first occurrence of an
+  // item in an array, or -1 if the item is not included in the array.
+  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
+  // If the array is large and already in sort order, pass `true`
+  // for **isSorted** to use binary search.
+  _.indexOf = function(array, item, isSorted) {
+    if (array == null) return -1;
+    var i, l;
+    if (isSorted) {
+      i = _.sortedIndex(array, item);
+      return array[i] === item ? i : -1;
+    }
+    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+    for (i = 0, l = array.length; i < l; i++) if (array[i] === item) return i;
+    return -1;
+  };
+
+
+  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
+  _.lastIndexOf = function(array, item) {
+    if (array == null) return -1;
+    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+    var i = array.length;
+    while (i--) if (array[i] === item) return i;
+    return -1;
+  };
+
+  // Generate an integer Array containing an arithmetic progression. A port of
+  // the native Python `range()` function. See
+  // [the Python documentation](http://docs.python.org/library/functions.html#range).
+  _.range = function(start, stop, step) {
+    if (arguments.length <= 1) {
+      stop = start || 0;
+      start = 0;
+    }
+    step = arguments[2] || 1;
+
+    var len = Math.max(Math.ceil((stop - start) / step), 0);
+    var idx = 0;
+    var range = new Array(len);
+
+    while(idx < len) {
+      range[idx++] = start;
+      start += step;
+    }
+
+    return range;
+  };
+
+  // Function (ahem) Functions
+  // ------------------
+
+  // Create a function bound to a given object (assigning `this`, and arguments,
+  // optionally). Binding with arguments is also known as `curry`.
+  // Delegates to **ECMAScript 5**'s native `Function.bind` if available.
+  // We check for `func.bind` first, to fail fast when `func` is undefined.
+  _.bind = function(func, obj) {
+    if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
+    var args = slice.call(arguments, 2);
+    return function() {
+      return func.apply(obj, args.concat(slice.call(arguments)));
+    };
+  };
+
+  // Bind all of an object's methods to that object. Useful for ensuring that
+  // all callbacks defined on an object belong to it.
+  _.bindAll = function(obj) {
+    var funcs = slice.call(arguments, 1);
+    if (funcs.length == 0) funcs = _.functions(obj);
+    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
+    return obj;
+  };
+
+  // Memoize an expensive function by storing its results.
+  _.memoize = function(func, hasher) {
+    var memo = {};
+    hasher || (hasher = _.identity);
+    return function() {
+      var key = hasher.apply(this, arguments);
+      return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
+    };
+  };
+
+  // Delays a function for the given number of milliseconds, and then calls
+  // it with the arguments supplied.
+  _.delay = function(func, wait) {
+    var args = slice.call(arguments, 2);
+    return setTimeout(function(){ return func.apply(func, args); }, wait);
+  };
+
+  // Defers a function, scheduling it to run after the current call stack has
+  // cleared.
+  _.defer = function(func) {
+    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
+  };
+
+  // Internal function used to implement `_.throttle` and `_.debounce`.
+  var limit = function(func, wait, debounce) {
+    var timeout;
+    return function() {
+      var context = this, args = arguments;
+      var throttler = function() {
+        timeout = null;
+        func.apply(context, args);
+      };
+      if (debounce) clearTimeout(timeout);
+      if (debounce || !timeout) timeout = setTimeout(throttler, wait);
+    };
+  };
+
+  // Returns a function, that, when invoked, will only be triggered at most once
+  // during a given window of time.
+  _.throttle = function(func, wait) {
+    return limit(func, wait, false);
+  };
+
+  // Returns a function, that, as long as it continues to be invoked, will not
+  // be triggered. The function will be called after it stops being called for
+  // N milliseconds.
+  _.debounce = function(func, wait) {
+    return limit(func, wait, true);
+  };
+
+  // Returns a function that will be executed at most one time, no matter how
+  // often you call it. Useful for lazy initialization.
+  _.once = function(func) {
+    var ran = false, memo;
+    return function() {
+      if (ran) return memo;
+      ran = true;
+      return memo = func.apply(this, arguments);
+    };
+  };
+
+  // Returns the first function passed as an argument to the second,
+  // allowing you to adjust arguments, run code before and after, and
+  // conditionally execute the original function.
+  _.wrap = function(func, wrapper) {
+    return function() {
+      var args = [func].concat(slice.call(arguments));
+      return wrapper.apply(this, args);
+    };
+  };
+
+  // Returns a function that is the composition of a list of functions, each
+  // consuming the return value of the function that follows.
+  _.compose = function() {
+    var funcs = slice.call(arguments);
+    return function() {
+      var args = slice.call(arguments);
+      for (var i=funcs.length-1; i >= 0; i--) {
+        args = [funcs[i].apply(this, args)];
+      }
+      return args[0];
+    };
+  };
+
+  // Returns a function that will only be executed after being called N times.
+  _.after = function(times, func) {
+    return function() {
+      if (--times < 1) { return func.apply(this, arguments); }
+    };
+  };
+
+
+  // Object Functions
+  // ----------------
+
+  // Retrieve the names of an object's properties.
+  // Delegates to **ECMAScript 5**'s native `Object.keys`
+  _.keys = nativeKeys || function(obj) {
+    if (obj !== Object(obj)) throw new TypeError('Invalid object');
+    var keys = [];
+    for (var key in obj) if (hasOwnProperty.call(obj, key)) keys[keys.length] = key;
+    return keys;
+  };
+
+  // Retrieve the values of an object's properties.
+  _.values = function(obj) {
+    return _.map(obj, _.identity);
+  };
+
+  // Return a sorted list of the function names available on the object.
+  // Aliased as `methods`
+  _.functions = _.methods = function(obj) {
+    return _.filter(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
+  };
+
+  // Extend a given object with all the properties in passed-in object(s).
+  _.extend = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      for (var prop in source) {
+        if (source[prop] !== void 0) obj[prop] = source[prop];
+      }
+    });
+    return obj;
+  };
+
+  // Fill in a given object with default properties.
+  _.defaults = function(obj) {
+    each(slice.call(arguments, 1), function(source) {
+      for (var prop in source) {
+        if (obj[prop] == null) obj[prop] = source[prop];
+      }
+    });
+    return obj;
+  };
+
+  // Create a (shallow-cloned) duplicate of an object.
+  _.clone = function(obj) {
+    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
+  };
+
+  // Invokes interceptor with the obj, and then returns obj.
+  // The primary purpose of this method is to "tap into" a method chain, in
+  // order to perform operations on intermediate results within the chain.
+  _.tap = function(obj, interceptor) {
+    interceptor(obj);
+    return obj;
+  };
+
+  // Perform a deep comparison to check if two objects are equal.
+  _.isEqual = function(a, b) {
+    // Check object identity.
+    if (a === b) return true;
+    // Different types?
+    var atype = typeof(a), btype = typeof(b);
+    if (atype != btype) return false;
+    // Basic equality test (watch out for coercions).
+    if (a == b) return true;
+    // One is falsy and the other truthy.
+    if ((!a && b) || (a && !b)) return false;
+    // Unwrap any wrapped objects.
+    if (a._chain) a = a._wrapped;
+    if (b._chain) b = b._wrapped;
+    // One of them implements an isEqual()?
+    if (a.isEqual) return a.isEqual(b);
+    // Check dates' integer values.
+    if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
+    // Both are NaN?
+    if (_.isNaN(a) && _.isNaN(b)) return false;
+    // Compare regular expressions.
+    if (_.isRegExp(a) && _.isRegExp(b))
+      return a.source     === b.source &&
+             a.global     === b.global &&
+             a.ignoreCase === b.ignoreCase &&
+             a.multiline  === b.multiline;
+    // If a is not an object by this point, we can't handle it.
+    if (atype !== 'object') return false;
+    // Check for different array lengths before comparing contents.
+    if (a.length && (a.length !== b.length)) return false;
+    // Nothing else worked, deep compare the contents.
+    var aKeys = _.keys(a), bKeys = _.keys(b);
+    // Different object sizes?
+    if (aKeys.length != bKeys.length) return false;
+    // Recursive comparison of contents.
+    for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
+    return true;
+  };
+
+  // Is a given array or object empty?
+  _.isEmpty = function(obj) {
+    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
+    for (var key in obj) if (hasOwnProperty.call(obj, key)) return false;
+    return true;
+  };
+
+  // Is a given value a DOM element?
+  _.isElement = function(obj) {
+    return !!(obj && obj.nodeType == 1);
+  };
+
+  // Is a given value an array?
+  // Delegates to ECMA5's native Array.isArray
+  _.isArray = nativeIsArray || function(obj) {
+    return toString.call(obj) === '[object Array]';
+  };
+
+  // Is a given variable an arguments object?
+  _.isArguments = function(obj) {
+    return !!(obj && hasOwnProperty.call(obj, 'callee'));
+  };
+
+  // Is a given value a function?
+  _.isFunction = function(obj) {
+    return !!(obj && obj.constructor && obj.call && obj.apply);
+  };
+
+  // Is a given value a string?
+  _.isString = function(obj) {
+    return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
+  };
+
+  // Is a given value a number?
+  _.isNumber = function(obj) {
+    return !!(obj === 0 || (obj && obj.toExponential && obj.toFixed));
+  };
+
+  // Is the given value `NaN`? `NaN` happens to be the only value in JavaScript
+  // that does not equal itself.
+  _.isNaN = function(obj) {
+    return obj !== obj;
+  };
+
+  // Is a given value a boolean?
+  _.isBoolean = function(obj) {
+    return obj === true || obj === false;
+  };
+
+  // Is a given value a date?
+  _.isDate = function(obj) {
+    return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
+  };
+
+  // Is the given value a regular expression?
+  _.isRegExp = function(obj) {
+    return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
+  };
+
+  // Is a given value equal to null?
+  _.isNull = function(obj) {
+    return obj === null;
+  };
+
+  // Is a given variable undefined?
+  _.isUndefined = function(obj) {
+    return obj === void 0;
+  };
+
+  // Utility Functions
+  // -----------------
+
+  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
+  // previous owner. Returns a reference to the Underscore object.
+  _.noConflict = function() {
+    root._ = previousUnderscore;
+    return this;
+  };
+
+  // Keep the identity function around for default iterators.
+  _.identity = function(value) {
+    return value;
+  };
+
+  // Run a function **n** times.
+  _.times = function (n, iterator, context) {
+    for (var i = 0; i < n; i++) iterator.call(context, i);
+  };
+
+  // Add your own custom functions to the Underscore object, ensuring that
+  // they're correctly added to the OOP wrapper as well.
+  _.mixin = function(obj) {
+    each(_.functions(obj), function(name){
+      addToWrapper(name, _[name] = obj[name]);
+    });
+  };
+
+  // Generate a unique integer id (unique within the entire client session).
+  // Useful for temporary DOM ids.
+  var idCounter = 0;
+  _.uniqueId = function(prefix) {
+    var id = idCounter++;
+    return prefix ? prefix + id : id;
+  };
+
+  // By default, Underscore uses ERB-style template delimiters, change the
+  // following template settings to use alternative delimiters.
+  _.templateSettings = {
+    evaluate    : /<%([\s\S]+?)%>/g,
+    interpolate : /<%=([\s\S]+?)%>/g
+  };
+
+  // JavaScript micro-templating, similar to John Resig's implementation.
+  // Underscore templating handles arbitrary delimiters, preserves whitespace,
+  // and correctly escapes quotes within interpolated code.
+  _.template = function(str, data) {
+    var c  = _.templateSettings;
+    var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
+      'with(obj||{}){__p.push(\'' +
+      str.replace(/\\/g, '\\\\')
+         .replace(/'/g, "\\'")
+         .replace(c.interpolate, function(match, code) {
+           return "'," + code.replace(/\\'/g, "'") + ",'";
+         })
+         .replace(c.evaluate || null, function(match, code) {
+           return "');" + code.replace(/\\'/g, "'")
+                              .replace(/[\r\n\t]/g, ' ') + "__p.push('";
+         })
+         .replace(/\r/g, '\\r')
+         .replace(/\n/g, '\\n')
+         .replace(/\t/g, '\\t')
+         + "');}return __p.join('');";
+    var func = new Function('obj', tmpl);
+    return data ? func(data) : func;
+  };
+
+  // The OOP Wrapper
+  // ---------------
+
+  // If Underscore is called as a function, it returns a wrapped object that
+  // can be used OO-style. This wrapper holds altered versions of all the
+  // underscore functions. Wrapped objects may be chained.
+  var wrapper = function(obj) { this._wrapped = obj; };
+
+  // Expose `wrapper.prototype` as `_.prototype`
+  _.prototype = wrapper.prototype;
+
+  // Helper function to continue chaining intermediate results.
+  var result = function(obj, chain) {
+    return chain ? _(obj).chain() : obj;
+  };
+
+  // A method to easily add functions to the OOP wrapper.
+  var addToWrapper = function(name, func) {
+    wrapper.prototype[name] = function() {
+      var args = slice.call(arguments);
+      unshift.call(args, this._wrapped);
+      return result(func.apply(_, args), this._chain);
+    };
+  };
+
+  // Add all of the Underscore functions to the wrapper object.
+  _.mixin(_);
+
+  // Add all mutator Array functions to the wrapper.
+  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
+    var method = ArrayProto[name];
+    wrapper.prototype[name] = function() {
+      method.apply(this._wrapped, arguments);
+      return result(this._wrapped, this._chain);
+    };
+  });
+
+  // Add all accessor Array functions to the wrapper.
+  each(['concat', 'join', 'slice'], function(name) {
+    var method = ArrayProto[name];
+    wrapper.prototype[name] = function() {
+      return result(method.apply(this._wrapped, arguments), this._chain);
+    };
+  });
+
+  // Start chaining a wrapped Underscore object.
+  wrapper.prototype.chain = function() {
+    this._chain = true;
+    return this;
+  };
+
+  // Extracts the result from a wrapped and chained object.
+  wrapper.prototype.value = function() {
+    return this._wrapped;
+  };
+
+})();
diff --git a/html/_static/up-pressed.png b/html/_static/up-pressed.png
new file mode 100644 (file)
index 0000000..8bd587a
Binary files /dev/null and b/html/_static/up-pressed.png differ
diff --git a/html/_static/up.png b/html/_static/up.png
new file mode 100644 (file)
index 0000000..b946256
Binary files /dev/null and b/html/_static/up.png differ
diff --git a/html/_static/websupport.js b/html/_static/websupport.js
new file mode 100644 (file)
index 0000000..e9bd1b8
--- /dev/null
@@ -0,0 +1,808 @@
+/*
+ * websupport.js
+ * ~~~~~~~~~~~~~
+ *
+ * sphinx.websupport utilties for all documentation.
+ *
+ * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+(function($) {
+  $.fn.autogrow = function() {
+    return this.each(function() {
+    var textarea = this;
+
+    $.fn.autogrow.resize(textarea);
+
+    $(textarea)
+      .focus(function() {
+        textarea.interval = setInterval(function() {
+          $.fn.autogrow.resize(textarea);
+        }, 500);
+      })
+      .blur(function() {
+        clearInterval(textarea.interval);
+      });
+    });
+  };
+
+  $.fn.autogrow.resize = function(textarea) {
+    var lineHeight = parseInt($(textarea).css('line-height'), 10);
+    var lines = textarea.value.split('\n');
+    var columns = textarea.cols;
+    var lineCount = 0;
+    $.each(lines, function() {
+      lineCount += Math.ceil(this.length / columns) || 1;
+    });
+    var height = lineHeight * (lineCount + 1);
+    $(textarea).css('height', height);
+  };
+})(jQuery);
+
+(function($) {
+  var comp, by;
+
+  function init() {
+    initEvents();
+    initComparator();
+  }
+
+  function initEvents() {
+    $('a.comment-close').live("click", function(event) {
+      event.preventDefault();
+      hide($(this).attr('id').substring(2));
+    });
+    $('a.vote').live("click", function(event) {
+      event.preventDefault();
+      handleVote($(this));
+    });
+    $('a.reply').live("click", function(event) {
+      event.preventDefault();
+      openReply($(this).attr('id').substring(2));
+    });
+    $('a.close-reply').live("click", function(event) {
+      event.preventDefault();
+      closeReply($(this).attr('id').substring(2));
+    });
+    $('a.sort-option').live("click", function(event) {
+      event.preventDefault();
+      handleReSort($(this));
+    });
+    $('a.show-proposal').live("click", function(event) {
+      event.preventDefault();
+      showProposal($(this).attr('id').substring(2));
+    });
+    $('a.hide-proposal').live("click", function(event) {
+      event.preventDefault();
+      hideProposal($(this).attr('id').substring(2));
+    });
+    $('a.show-propose-change').live("click", function(event) {
+      event.preventDefault();
+      showProposeChange($(this).attr('id').substring(2));
+    });
+    $('a.hide-propose-change').live("click", function(event) {
+      event.preventDefault();
+      hideProposeChange($(this).attr('id').substring(2));
+    });
+    $('a.accept-comment').live("click", function(event) {
+      event.preventDefault();
+      acceptComment($(this).attr('id').substring(2));
+    });
+    $('a.delete-comment').live("click", function(event) {
+      event.preventDefault();
+      deleteComment($(this).attr('id').substring(2));
+    });
+    $('a.comment-markup').live("click", function(event) {
+      event.preventDefault();
+      toggleCommentMarkupBox($(this).attr('id').substring(2));
+    });
+  }
+
+  /**
+   * Set comp, which is a comparator function used for sorting and
+   * inserting comments into the list.
+   */
+  function setComparator() {
+    // If the first three letters are "asc", sort in ascending order
+    // and remove the prefix.
+    if (by.substring(0,3) == 'asc') {
+      var i = by.substring(3);
+      comp = function(a, b) { return a[i] - b[i]; };
+    } else {
+      // Otherwise sort in descending order.
+      comp = function(a, b) { return b[by] - a[by]; };
+    }
+
+    // Reset link styles and format the selected sort option.
+    $('a.sel').attr('href', '#').removeClass('sel');
+    $('a.by' + by).removeAttr('href').addClass('sel');
+  }
+
+  /**
+   * Create a comp function. If the user has preferences stored in
+   * the sortBy cookie, use those, otherwise use the default.
+   */
+  function initComparator() {
+    by = 'rating'; // Default to sort by rating.
+    // If the sortBy cookie is set, use that instead.
+    if (document.cookie.length > 0) {
+      var start = document.cookie.indexOf('sortBy=');
+      if (start != -1) {
+        start = start + 7;
+        var end = document.cookie.indexOf(";", start);
+        if (end == -1) {
+          end = document.cookie.length;
+          by = unescape(document.cookie.substring(start, end));
+        }
+      }
+    }
+    setComparator();
+  }
+
+  /**
+   * Show a comment div.
+   */
+  function show(id) {
+    $('#ao' + id).hide();
+    $('#ah' + id).show();
+    var context = $.extend({id: id}, opts);
+    var popup = $(renderTemplate(popupTemplate, context)).hide();
+    popup.find('textarea[name="proposal"]').hide();
+    popup.find('a.by' + by).addClass('sel');
+    var form = popup.find('#cf' + id);
+    form.submit(function(event) {
+      event.preventDefault();
+      addComment(form);
+    });
+    $('#s' + id).after(popup);
+    popup.slideDown('fast', function() {
+      getComments(id);
+    });
+  }
+
+  /**
+   * Hide a comment div.
+   */
+  function hide(id) {
+    $('#ah' + id).hide();
+    $('#ao' + id).show();
+    var div = $('#sc' + id);
+    div.slideUp('fast', function() {
+      div.remove();
+    });
+  }
+
+  /**
+   * Perform an ajax request to get comments for a node
+   * and insert the comments into the comments tree.
+   */
+  function getComments(id) {
+    $.ajax({
+     type: 'GET',
+     url: opts.getCommentsURL,
+     data: {node: id},
+     success: function(data, textStatus, request) {
+       var ul = $('#cl' + id);
+       var speed = 100;
+       $('#cf' + id)
+         .find('textarea[name="proposal"]')
+         .data('source', data.source);
+
+       if (data.comments.length === 0) {
+         ul.html('<li>No comments yet.</li>');
+         ul.data('empty', true);
+       } else {
+         // If there are comments, sort them and put them in the list.
+         var comments = sortComments(data.comments);
+         speed = data.comments.length * 100;
+         appendComments(comments, ul);
+         ul.data('empty', false);
+       }
+       $('#cn' + id).slideUp(speed + 200);
+       ul.slideDown(speed);
+     },
+     error: function(request, textStatus, error) {
+       showError('Oops, there was a problem retrieving the comments.');
+     },
+     dataType: 'json'
+    });
+  }
+
+  /**
+   * Add a comment via ajax and insert the comment into the comment tree.
+   */
+  function addComment(form) {
+    var node_id = form.find('input[name="node"]').val();
+    var parent_id = form.find('input[name="parent"]').val();
+    var text = form.find('textarea[name="comment"]').val();
+    var proposal = form.find('textarea[name="proposal"]').val();
+
+    if (text == '') {
+      showError('Please enter a comment.');
+      return;
+    }
+
+    // Disable the form that is being submitted.
+    form.find('textarea,input').attr('disabled', 'disabled');
+
+    // Send the comment to the server.
+    $.ajax({
+      type: "POST",
+      url: opts.addCommentURL,
+      dataType: 'json',
+      data: {
+        node: node_id,
+        parent: parent_id,
+        text: text,
+        proposal: proposal
+      },
+      success: function(data, textStatus, error) {
+        // Reset the form.
+        if (node_id) {
+          hideProposeChange(node_id);
+        }
+        form.find('textarea')
+          .val('')
+          .add(form.find('input'))
+          .removeAttr('disabled');
+       var ul = $('#cl' + (node_id || parent_id));
+        if (ul.data('empty')) {
+          $(ul).empty();
+          ul.data('empty', false);
+        }
+        insertComment(data.comment);
+        var ao = $('#ao' + node_id);
+        ao.find('img').attr({'src': opts.commentBrightImage});
+        if (node_id) {
+          // if this was a "root" comment, remove the commenting box
+          // (the user can get it back by reopening the comment popup)
+          $('#ca' + node_id).slideUp();
+        }
+      },
+      error: function(request, textStatus, error) {
+        form.find('textarea,input').removeAttr('disabled');
+        showError('Oops, there was a problem adding the comment.');
+      }
+    });
+  }
+
+  /**
+   * Recursively append comments to the main comment list and children
+   * lists, creating the comment tree.
+   */
+  function appendComments(comments, ul) {
+    $.each(comments, function() {
+      var div = createCommentDiv(this);
+      ul.append($(document.createElement('li')).html(div));
+      appendComments(this.children, div.find('ul.comment-children'));
+      // To avoid stagnating data, don't store the comments children in data.
+      this.children = null;
+      div.data('comment', this);
+    });
+  }
+
+  /**
+   * After adding a new comment, it must be inserted in the correct
+   * location in the comment tree.
+   */
+  function insertComment(comment) {
+    var div = createCommentDiv(comment);
+
+    // To avoid stagnating data, don't store the comments children in data.
+    comment.children = null;
+    div.data('comment', comment);
+
+    var ul = $('#cl' + (comment.node || comment.parent));
+    var siblings = getChildren(ul);
+
+    var li = $(document.createElement('li'));
+    li.hide();
+
+    // Determine where in the parents children list to insert this comment.
+    for(i=0; i < siblings.length; i++) {
+      if (comp(comment, siblings[i]) <= 0) {
+        $('#cd' + siblings[i].id)
+          .parent()
+          .before(li.html(div));
+        li.slideDown('fast');
+        return;
+      }
+    }
+
+    // If we get here, this comment rates lower than all the others,
+    // or it is the only comment in the list.
+    ul.append(li.html(div));
+    li.slideDown('fast');
+  }
+
+  function acceptComment(id) {
+    $.ajax({
+      type: 'POST',
+      url: opts.acceptCommentURL,
+      data: {id: id},
+      success: function(data, textStatus, request) {
+        $('#cm' + id).fadeOut('fast');
+        $('#cd' + id).removeClass('moderate');
+      },
+      error: function(request, textStatus, error) {
+        showError('Oops, there was a problem accepting the comment.');
+      }
+    });
+  }
+
+  function deleteComment(id) {
+    $.ajax({
+      type: 'POST',
+      url: opts.deleteCommentURL,
+      data: {id: id},
+      success: function(data, textStatus, request) {
+        var div = $('#cd' + id);
+        if (data == 'delete') {
+          // Moderator mode: remove the comment and all children immediately
+          div.slideUp('fast', function() {
+            div.remove();
+          });
+          return;
+        }
+        // User mode: only mark the comment as deleted
+        div
+          .find('span.user-id:first')
+          .text('[deleted]').end()
+          .find('div.comment-text:first')
+          .text('[deleted]').end()
+          .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
+                ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
+          .remove();
+        var comment = div.data('comment');
+        comment.username = '[deleted]';
+        comment.text = '[deleted]';
+        div.data('comment', comment);
+      },
+      error: function(request, textStatus, error) {
+        showError('Oops, there was a problem deleting the comment.');
+      }
+    });
+  }
+
+  function showProposal(id) {
+    $('#sp' + id).hide();
+    $('#hp' + id).show();
+    $('#pr' + id).slideDown('fast');
+  }
+
+  function hideProposal(id) {
+    $('#hp' + id).hide();
+    $('#sp' + id).show();
+    $('#pr' + id).slideUp('fast');
+  }
+
+  function showProposeChange(id) {
+    $('#pc' + id).hide();
+    $('#hc' + id).show();
+    var textarea = $('#pt' + id);
+    textarea.val(textarea.data('source'));
+    $.fn.autogrow.resize(textarea[0]);
+    textarea.slideDown('fast');
+  }
+
+  function hideProposeChange(id) {
+    $('#hc' + id).hide();
+    $('#pc' + id).show();
+    var textarea = $('#pt' + id);
+    textarea.val('').removeAttr('disabled');
+    textarea.slideUp('fast');
+  }
+
+  function toggleCommentMarkupBox(id) {
+    $('#mb' + id).toggle();
+  }
+
+  /** Handle when the user clicks on a sort by link. */
+  function handleReSort(link) {
+    var classes = link.attr('class').split(/\s+/);
+    for (var i=0; i<classes.length; i++) {
+      if (classes[i] != 'sort-option') {
+       by = classes[i].substring(2);
+      }
+    }
+    setComparator();
+    // Save/update the sortBy cookie.
+    var expiration = new Date();
+    expiration.setDate(expiration.getDate() + 365);
+    document.cookie= 'sortBy=' + escape(by) +
+                     ';expires=' + expiration.toUTCString();
+    $('ul.comment-ul').each(function(index, ul) {
+      var comments = getChildren($(ul), true);
+      comments = sortComments(comments);
+      appendComments(comments, $(ul).empty());
+    });
+  }
+
+  /**
+   * Function to process a vote when a user clicks an arrow.
+   */
+  function handleVote(link) {
+    if (!opts.voting) {
+      showError("You'll need to login to vote.");
+      return;
+    }
+
+    var id = link.attr('id');
+    if (!id) {
+      // Didn't click on one of the voting arrows.
+      return;
+    }
+    // If it is an unvote, the new vote value is 0,
+    // Otherwise it's 1 for an upvote, or -1 for a downvote.
+    var value = 0;
+    if (id.charAt(1) != 'u') {
+      value = id.charAt(0) == 'u' ? 1 : -1;
+    }
+    // The data to be sent to the server.
+    var d = {
+      comment_id: id.substring(2),
+      value: value
+    };
+
+    // Swap the vote and unvote links.
+    link.hide();
+    $('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
+      .show();
+
+    // The div the comment is displayed in.
+    var div = $('div#cd' + d.comment_id);
+    var data = div.data('comment');
+
+    // If this is not an unvote, and the other vote arrow has
+    // already been pressed, unpress it.
+    if ((d.value !== 0) && (data.vote === d.value * -1)) {
+      $('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
+      $('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
+    }
+
+    // Update the comments rating in the local data.
+    data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
+    data.vote = d.value;
+    div.data('comment', data);
+
+    // Change the rating text.
+    div.find('.rating:first')
+      .text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
+
+    // Send the vote information to the server.
+    $.ajax({
+      type: "POST",
+      url: opts.processVoteURL,
+      data: d,
+      error: function(request, textStatus, error) {
+        showError('Oops, there was a problem casting that vote.');
+      }
+    });
+  }
+
+  /**
+   * Open a reply form used to reply to an existing comment.
+   */
+  function openReply(id) {
+    // Swap out the reply link for the hide link
+    $('#rl' + id).hide();
+    $('#cr' + id).show();
+
+    // Add the reply li to the children ul.
+    var div = $(renderTemplate(replyTemplate, {id: id})).hide();
+    $('#cl' + id)
+      .prepend(div)
+      // Setup the submit handler for the reply form.
+      .find('#rf' + id)
+      .submit(function(event) {
+        event.preventDefault();
+        addComment($('#rf' + id));
+        closeReply(id);
+      })
+      .find('input[type=button]')
+      .click(function() {
+        closeReply(id);
+      });
+    div.slideDown('fast', function() {
+      $('#rf' + id).find('textarea').focus();
+    });
+  }
+
+  /**
+   * Close the reply form opened with openReply.
+   */
+  function closeReply(id) {
+    // Remove the reply div from the DOM.
+    $('#rd' + id).slideUp('fast', function() {
+      $(this).remove();
+    });
+
+    // Swap out the hide link for the reply link
+    $('#cr' + id).hide();
+    $('#rl' + id).show();
+  }
+
+  /**
+   * Recursively sort a tree of comments using the comp comparator.
+   */
+  function sortComments(comments) {
+    comments.sort(comp);
+    $.each(comments, function() {
+      this.children = sortComments(this.children);
+    });
+    return comments;
+  }
+
+  /**
+   * Get the children comments from a ul. If recursive is true,
+   * recursively include childrens' children.
+   */
+  function getChildren(ul, recursive) {
+    var children = [];
+    ul.children().children("[id^='cd']")
+      .each(function() {
+        var comment = $(this).data('comment');
+        if (recursive)
+          comment.children = getChildren($(this).find('#cl' + comment.id), true);
+        children.push(comment);
+      });
+    return children;
+  }
+
+  /** Create a div to display a comment in. */
+  function createCommentDiv(comment) {
+    if (!comment.displayed && !opts.moderator) {
+      return $('<div class="moderate">Thank you!  Your comment will show up '
+               + 'once it is has been approved by a moderator.</div>');
+    }
+    // Prettify the comment rating.
+    comment.pretty_rating = comment.rating + ' point' +
+      (comment.rating == 1 ? '' : 's');
+    // Make a class (for displaying not yet moderated comments differently)
+    comment.css_class = comment.displayed ? '' : ' moderate';
+    // Create a div for this comment.
+    var context = $.extend({}, opts, comment);
+    var div = $(renderTemplate(commentTemplate, context));
+
+    // If the user has voted on this comment, highlight the correct arrow.
+    if (comment.vote) {
+      var direction = (comment.vote == 1) ? 'u' : 'd';
+      div.find('#' + direction + 'v' + comment.id).hide();
+      div.find('#' + direction + 'u' + comment.id).show();
+    }
+
+    if (opts.moderator || comment.text != '[deleted]') {
+      div.find('a.reply').show();
+      if (comment.proposal_diff)
+        div.find('#sp' + comment.id).show();
+      if (opts.moderator && !comment.displayed)
+        div.find('#cm' + comment.id).show();
+      if (opts.moderator || (opts.username == comment.username))
+        div.find('#dc' + comment.id).show();
+    }
+    return div;
+  }
+
+  /**
+   * A simple template renderer. Placeholders such as <%id%> are replaced
+   * by context['id'] with items being escaped. Placeholders such as <#id#>
+   * are not escaped.
+   */
+  function renderTemplate(template, context) {
+    var esc = $(document.createElement('div'));
+
+    function handle(ph, escape) {
+      var cur = context;
+      $.each(ph.split('.'), function() {
+        cur = cur[this];
+      });
+      return escape ? esc.text(cur || "").html() : cur;
+    }
+
+    return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
+      return handle(arguments[2], arguments[1] == '%' ? true : false);
+    });
+  }
+
+  /** Flash an error message briefly. */
+  function showError(message) {
+    $(document.createElement('div')).attr({'class': 'popup-error'})
+      .append($(document.createElement('div'))
+               .attr({'class': 'error-message'}).text(message))
+      .appendTo('body')
+      .fadeIn("slow")
+      .delay(2000)
+      .fadeOut("slow");
+  }
+
+  /** Add a link the user uses to open the comments popup. */
+  $.fn.comment = function() {
+    return this.each(function() {
+      var id = $(this).attr('id').substring(1);
+      var count = COMMENT_METADATA[id];
+      var title = count + ' comment' + (count == 1 ? '' : 's');
+      var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
+      var addcls = count == 0 ? ' nocomment' : '';
+      $(this)
+        .append(
+          $(document.createElement('a')).attr({
+            href: '#',
+            'class': 'sphinx-comment-open' + addcls,
+            id: 'ao' + id
+          })
+            .append($(document.createElement('img')).attr({
+              src: image,
+              alt: 'comment',
+              title: title
+            }))
+            .click(function(event) {
+              event.preventDefault();
+              show($(this).attr('id').substring(2));
+            })
+        )
+        .append(
+          $(document.createElement('a')).attr({
+            href: '#',
+            'class': 'sphinx-comment-close hidden',
+            id: 'ah' + id
+          })
+            .append($(document.createElement('img')).attr({
+              src: opts.closeCommentImage,
+              alt: 'close',
+              title: 'close'
+            }))
+            .click(function(event) {
+              event.preventDefault();
+              hide($(this).attr('id').substring(2));
+            })
+        );
+    });
+  };
+
+  var opts = {
+    processVoteURL: '/_process_vote',
+    addCommentURL: '/_add_comment',
+    getCommentsURL: '/_get_comments',
+    acceptCommentURL: '/_accept_comment',
+    deleteCommentURL: '/_delete_comment',
+    commentImage: '/static/_static/comment.png',
+    closeCommentImage: '/static/_static/comment-close.png',
+    loadingImage: '/static/_static/ajax-loader.gif',
+    commentBrightImage: '/static/_static/comment-bright.png',
+    upArrow: '/static/_static/up.png',
+    downArrow: '/static/_static/down.png',
+    upArrowPressed: '/static/_static/up-pressed.png',
+    downArrowPressed: '/static/_static/down-pressed.png',
+    voting: false,
+    moderator: false
+  };
+
+  if (typeof COMMENT_OPTIONS != "undefined") {
+    opts = jQuery.extend(opts, COMMENT_OPTIONS);
+  }
+
+  var popupTemplate = '\
+    <div class="sphinx-comments" id="sc<%id%>">\
+      <p class="sort-options">\
+        Sort by:\
+        <a href="#" class="sort-option byrating">best rated</a>\
+        <a href="#" class="sort-option byascage">newest</a>\
+        <a href="#" class="sort-option byage">oldest</a>\
+      </p>\
+      <div class="comment-header">Comments</div>\
+      <div class="comment-loading" id="cn<%id%>">\
+        loading comments... <img src="<%loadingImage%>" alt="" /></div>\
+      <ul id="cl<%id%>" class="comment-ul"></ul>\
+      <div id="ca<%id%>">\
+      <p class="add-a-comment">Add a comment\
+        (<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
+      <div class="comment-markup-box" id="mb<%id%>">\
+        reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
+        <tt>``code``</tt>, \
+        code blocks: <tt>::</tt> and an indented block after blank line</div>\
+      <form method="post" id="cf<%id%>" class="comment-form" action="">\
+        <textarea name="comment" cols="80"></textarea>\
+        <p class="propose-button">\
+          <a href="#" id="pc<%id%>" class="show-propose-change">\
+            Propose a change &#9657;\
+          </a>\
+          <a href="#" id="hc<%id%>" class="hide-propose-change">\
+            Propose a change &#9663;\
+          </a>\
+        </p>\
+        <textarea name="proposal" id="pt<%id%>" cols="80"\
+                  spellcheck="false"></textarea>\
+        <input type="submit" value="Add comment" />\
+        <input type="hidden" name="node" value="<%id%>" />\
+        <input type="hidden" name="parent" value="" />\
+      </form>\
+      </div>\
+    </div>';
+
+  var commentTemplate = '\
+    <div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
+      <div class="vote">\
+        <div class="arrow">\
+          <a href="#" id="uv<%id%>" class="vote" title="vote up">\
+            <img src="<%upArrow%>" />\
+          </a>\
+          <a href="#" id="uu<%id%>" class="un vote" title="vote up">\
+            <img src="<%upArrowPressed%>" />\
+          </a>\
+        </div>\
+        <div class="arrow">\
+          <a href="#" id="dv<%id%>" class="vote" title="vote down">\
+            <img src="<%downArrow%>" id="da<%id%>" />\
+          </a>\
+          <a href="#" id="du<%id%>" class="un vote" title="vote down">\
+            <img src="<%downArrowPressed%>" />\
+          </a>\
+        </div>\
+      </div>\
+      <div class="comment-content">\
+        <p class="tagline comment">\
+          <span class="user-id"><%username%></span>\
+          <span class="rating"><%pretty_rating%></span>\
+          <span class="delta"><%time.delta%></span>\
+        </p>\
+        <div class="comment-text comment"><#text#></div>\
+        <p class="comment-opts comment">\
+          <a href="#" class="reply hidden" id="rl<%id%>">reply &#9657;</a>\
+          <a href="#" class="close-reply" id="cr<%id%>">reply &#9663;</a>\
+          <a href="#" id="sp<%id%>" class="show-proposal">proposal &#9657;</a>\
+          <a href="#" id="hp<%id%>" class="hide-proposal">proposal &#9663;</a>\
+          <a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
+          <span id="cm<%id%>" class="moderation hidden">\
+            <a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
+          </span>\
+        </p>\
+        <pre class="proposal" id="pr<%id%>">\
+<#proposal_diff#>\
+        </pre>\
+          <ul class="comment-children" id="cl<%id%>"></ul>\
+        </div>\
+        <div class="clearleft"></div>\
+      </div>\
+    </div>';
+
+  var replyTemplate = '\
+    <li>\
+      <div class="reply-div" id="rd<%id%>">\
+        <form id="rf<%id%>">\
+          <textarea name="comment" cols="80"></textarea>\
+          <input type="submit" value="Add reply" />\
+          <input type="button" value="Cancel" />\
+          <input type="hidden" name="parent" value="<%id%>" />\
+          <input type="hidden" name="node" value="" />\
+        </form>\
+      </div>\
+    </li>';
+
+  $(document).ready(function() {
+    init();
+  });
+})(jQuery);
+
+$(document).ready(function() {
+  // add comment anchors for all paragraphs that are commentable
+  $('.sphinx-has-comment').comment();
+
+  // highlight search words in search results
+  $("div.context").each(function() {
+    var params = $.getQueryParameters();
+    var terms = (params.q) ? params.q[0].split(/\s+/) : [];
+    var result = $(this);
+    $.each(terms, function() {
+      result.highlightText(this.toLowerCase(), 'highlighted');
+    });
+  });
+
+  // directly open comment window if requested
+  var anchor = document.location.hash;
+  if (anchor.substring(0, 9) == '#comment-') {
+    $('#ao' + anchor.substring(9)).click();
+    document.location.hash = '#s' + anchor.substring(9);
+  }
+});
diff --git a/html/api.html b/html/api.html
new file mode 100644 (file)
index 0000000..950bc9b
--- /dev/null
@@ -0,0 +1,1548 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>API Reference &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="List of available Plugins" href="plugins/index.html" />
+    <link rel="prev" title="SimpleTemplate Engine" href="stpl.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="plugins/index.html" title="List of available Plugins"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="stpl.html" title="SimpleTemplate Engine"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="module-bottle">
+<span id="api-reference"></span><h1>API Reference<a class="headerlink" href="#module-bottle" title="Permalink to this headline">¶</a></h1>
+<p>This is a mostly auto-generated API. If you are new to bottle, you might find the
+narrative <a class="reference internal" href="tutorial.html"><em>Tutorial</em></a> more helpful.</p>
+<div class="section" id="module-contents">
+<h2>Module Contents<a class="headerlink" href="#module-contents" title="Permalink to this headline">¶</a></h2>
+<p>The module defines several functions, constants, and an exception.</p>
+<dl class="function">
+<dt id="bottle.debug">
+<tt class="descname">debug</tt><big>(</big><em>mode=True</em><big>)</big><a class="reference internal" href="_modules/bottle.html#debug"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.debug" title="Permalink to this definition">¶</a></dt>
+<dd><p>Change the debug level.
+There is only one debug level supported at the moment.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.run">
+<tt class="descname">run</tt><big>(</big><em>app=None</em>, <em>server='wsgiref'</em>, <em>host='127.0.0.1'</em>, <em>port=8080</em>, <em>interval=1</em>, <em>reloader=False</em>, <em>quiet=False</em>, <em>plugins=None</em>, <em>debug=False</em>, <em>**kargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#run"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.run" title="Permalink to this definition">¶</a></dt>
+<dd><p>Start a server instance. This method blocks until the server terminates.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>app</strong> &#8211; WSGI application or target string supported by
+<a class="reference internal" href="#bottle.load_app" title="bottle.load_app"><tt class="xref py py-func docutils literal"><span class="pre">load_app()</span></tt></a>. (default: <a class="reference internal" href="#bottle.default_app" title="bottle.default_app"><tt class="xref py py-func docutils literal"><span class="pre">default_app()</span></tt></a>)</li>
+<li><strong>server</strong> &#8211; Server adapter to use. See <tt class="xref py py-data docutils literal"><span class="pre">server_names</span></tt> keys
+for valid names or pass a <tt class="xref py py-class docutils literal"><span class="pre">ServerAdapter</span></tt> subclass.
+(default: <cite>wsgiref</cite>)</li>
+<li><strong>host</strong> &#8211; Server address to bind to. Pass <tt class="docutils literal"><span class="pre">0.0.0.0</span></tt> to listens on
+all interfaces including the external one. (default: 127.0.0.1)</li>
+<li><strong>port</strong> &#8211; Server port to bind to. Values below 1024 require root
+privileges. (default: 8080)</li>
+<li><strong>reloader</strong> &#8211; Start auto-reloading server? (default: False)</li>
+<li><strong>interval</strong> &#8211; Auto-reloader interval in seconds (default: 1)</li>
+<li><strong>quiet</strong> &#8211; Suppress output to stdout and stderr? (default: False)</li>
+<li><strong>options</strong> &#8211; Options passed to the server adapter.</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.load">
+<tt class="descname">load</tt><big>(</big><em>target</em>, <em>**namespace</em><big>)</big><a class="reference internal" href="_modules/bottle.html#load"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.load" title="Permalink to this definition">¶</a></dt>
+<dd><p>Import a module or fetch an object from a module.</p>
+<ul class="simple">
+<li><tt class="docutils literal"><span class="pre">package.module</span></tt> returns <cite>module</cite> as a module object.</li>
+<li><tt class="docutils literal"><span class="pre">pack.mod:name</span></tt> returns the module variable <cite>name</cite> from <cite>pack.mod</cite>.</li>
+<li><tt class="docutils literal"><span class="pre">pack.mod:func()</span></tt> calls <cite>pack.mod.func()</cite> and returns the result.</li>
+</ul>
+<p>The last form accepts not only function calls, but any type of
+expression. Keyword arguments passed to this function are available as
+local variables. Example: <tt class="docutils literal"><span class="pre">import_string('re:compile(x)',</span> <span class="pre">x='[a-z]')</span></tt></p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.load_app">
+<tt class="descname">load_app</tt><big>(</big><em>target</em><big>)</big><a class="reference internal" href="_modules/bottle.html#load_app"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.load_app" title="Permalink to this definition">¶</a></dt>
+<dd><p>Load a bottle application from a module and make sure that the import
+does not affect the current default application, but returns a separate
+application object. See <a class="reference internal" href="#bottle.load" title="bottle.load"><tt class="xref py py-func docutils literal"><span class="pre">load()</span></tt></a> for the target parameter.</p>
+</dd></dl>
+
+<dl class="data">
+<dt id="bottle.request">
+<tt class="descname">request</tt><em class="property"> = &lt;LocalRequest: GET http://127.0.0.1/&gt;</em><a class="headerlink" href="#bottle.request" title="Permalink to this definition">¶</a></dt>
+<dd><p>A thread-safe instance of <a class="reference internal" href="#bottle.LocalRequest" title="bottle.LocalRequest"><tt class="xref py py-class docutils literal"><span class="pre">LocalRequest</span></tt></a>. If accessed from within a
+request callback, this instance always refers to the <em>current</em> request
+(even on a multithreaded server).</p>
+</dd></dl>
+
+<dl class="data">
+<dt id="bottle.response">
+<tt class="descname">response</tt><em class="property"> = Content-Type: text/html; charset=UTF-8 </em><a class="headerlink" href="#bottle.response" title="Permalink to this definition">¶</a></dt>
+<dd><p>A thread-safe instance of <a class="reference internal" href="#bottle.LocalResponse" title="bottle.LocalResponse"><tt class="xref py py-class docutils literal"><span class="pre">LocalResponse</span></tt></a>. It is used to change the
+HTTP response for the <em>current</em> request.</p>
+</dd></dl>
+
+<dl class="data">
+<dt id="bottle.HTTP_CODES">
+<tt class="descname">HTTP_CODES</tt><em class="property"> = {300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found', 303: 'See Other', 304: 'Not Modified', 305: 'Use Proxy', 306: '(Unused)', 307: 'Temporary Redirect', 100: 'Continue', 101: 'Switching Protocols', 400: 'Bad Request', 401: 'Unauthorized', 402: 'Payment Required', 403: 'Forbidden', 404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable', 407: 'Proxy Authentication Required', 408: 'Request Timeout', 409: 'Conflict', 410: 'Gone', 411: 'Length Required', 412: 'Precondition Failed', 413: 'Request Entity Too Large', 414: 'Request-URI Too Long', 415: 'Unsupported Media Type', 416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed', 418: &quot;I'm a teapot&quot;, 428: 'Precondition Required', 429: 'Too Many Requests', 431: 'Request Header Fields Too Large', 200: 'OK', 201: 'Created', 202: 'Accepted', 203: 'Non-Authoritative Information', 204: 'No Content', 205: 'Reset Content', 206: 'Partial Content', 500: 'Internal Server Error', 501: 'Not Implemented', 502: 'Bad Gateway', 503: 'Service Unavailable', 504: 'Gateway Timeout', 505: 'HTTP Version Not Supported', 511: 'Network Authentication Required'}</em><a class="headerlink" href="#bottle.HTTP_CODES" title="Permalink to this definition">¶</a></dt>
+<dd><p>A dict to map HTTP status codes (e.g. 404) to phrases (e.g. &#8216;Not Found&#8217;)</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.app">
+<tt class="descname">app</tt><big>(</big><big>)</big><a class="headerlink" href="#bottle.app" title="Permalink to this definition">¶</a></dt>
+<dt id="bottle.default_app">
+<tt class="descname">default_app</tt><big>(</big><big>)</big><a class="headerlink" href="#bottle.default_app" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the current <a class="reference internal" href="tutorial.html#default-app"><em>Default Application</em></a>. Actually, these are callable instances of <a class="reference internal" href="#bottle.AppStack" title="bottle.AppStack"><tt class="xref py py-class docutils literal"><span class="pre">AppStack</span></tt></a> and implement a stack-like API.</p>
+</dd></dl>
+
+<div class="section" id="routing">
+<h3>Routing<a class="headerlink" href="#routing" title="Permalink to this headline">¶</a></h3>
+<p>Bottle maintains a stack of <a class="reference internal" href="#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> instances (see <a class="reference internal" href="#bottle.app" title="bottle.app"><tt class="xref py py-func docutils literal"><span class="pre">app()</span></tt></a> and <a class="reference internal" href="#bottle.AppStack" title="bottle.AppStack"><tt class="xref py py-class docutils literal"><span class="pre">AppStack</span></tt></a>) and uses the top of the stack as a <em>default application</em> for some of the module-level functions and decorators.</p>
+<dl class="function">
+<dt id="bottle.route">
+<tt class="descname">route</tt><big>(</big><em>path</em>, <em>method='GET'</em>, <em>callback=None</em>, <em>**options</em><big>)</big><a class="headerlink" href="#bottle.route" title="Permalink to this definition">¶</a></dt>
+<dt id="bottle.get">
+<tt class="descname">get</tt><big>(</big><em>...</em><big>)</big><a class="headerlink" href="#bottle.get" title="Permalink to this definition">¶</a></dt>
+<dt id="bottle.post">
+<tt class="descname">post</tt><big>(</big><em>...</em><big>)</big><a class="headerlink" href="#bottle.post" title="Permalink to this definition">¶</a></dt>
+<dt id="bottle.put">
+<tt class="descname">put</tt><big>(</big><em>...</em><big>)</big><a class="headerlink" href="#bottle.put" title="Permalink to this definition">¶</a></dt>
+<dt id="bottle.delete">
+<tt class="descname">delete</tt><big>(</big><em>...</em><big>)</big><a class="headerlink" href="#bottle.delete" title="Permalink to this definition">¶</a></dt>
+<dd><p>Decorator to install a route to the current default application. See <a class="reference internal" href="#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a> for details.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.error">
+<tt class="descname">error</tt><big>(</big><em>...</em><big>)</big><a class="headerlink" href="#bottle.error" title="Permalink to this definition">¶</a></dt>
+<dd><p>Decorator to install an error handler to the current default application. See <a class="reference internal" href="#bottle.Bottle.error" title="bottle.Bottle.error"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.error()</span></tt></a> for details.</p>
+</dd></dl>
+
+</div>
+<div class="section" id="wsgi-and-http-utilities">
+<h3>WSGI and HTTP Utilities<a class="headerlink" href="#wsgi-and-http-utilities" title="Permalink to this headline">¶</a></h3>
+<dl class="function">
+<dt id="bottle.parse_date">
+<tt class="descname">parse_date</tt><big>(</big><em>ims</em><big>)</big><a class="reference internal" href="_modules/bottle.html#parse_date"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.parse_date" title="Permalink to this definition">¶</a></dt>
+<dd><p>Parse rfc1123, rfc850 and asctime timestamps and return UTC epoch.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.parse_auth">
+<tt class="descname">parse_auth</tt><big>(</big><em>header</em><big>)</big><a class="reference internal" href="_modules/bottle.html#parse_auth"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.parse_auth" title="Permalink to this definition">¶</a></dt>
+<dd><p>Parse rfc2617 HTTP authentication header string (basic) and return (user,pass) tuple or None</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.cookie_encode">
+<tt class="descname">cookie_encode</tt><big>(</big><em>data</em>, <em>key</em><big>)</big><a class="reference internal" href="_modules/bottle.html#cookie_encode"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.cookie_encode" title="Permalink to this definition">¶</a></dt>
+<dd><p>Encode and sign a pickle-able object. Return a (byte) string</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.cookie_decode">
+<tt class="descname">cookie_decode</tt><big>(</big><em>data</em>, <em>key</em><big>)</big><a class="reference internal" href="_modules/bottle.html#cookie_decode"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.cookie_decode" title="Permalink to this definition">¶</a></dt>
+<dd><p>Verify and decode an encoded string. Return an object or None.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.cookie_is_encoded">
+<tt class="descname">cookie_is_encoded</tt><big>(</big><em>data</em><big>)</big><a class="reference internal" href="_modules/bottle.html#cookie_is_encoded"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.cookie_is_encoded" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return True if the argument looks like a encoded cookie.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.yieldroutes">
+<tt class="descname">yieldroutes</tt><big>(</big><em>func</em><big>)</big><a class="reference internal" href="_modules/bottle.html#yieldroutes"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.yieldroutes" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return a generator for routes that match the signature (name, args)
+of the func parameter. This may yield more than one route if the function
+takes optional keyword arguments. The output is best described by example:</p>
+<div class="highlight-python"><pre>a()         -&gt; '/a'
+b(x, y)     -&gt; '/b/:x/:y'
+c(x, y=5)   -&gt; '/c/:x' and '/c/:x/:y'
+d(x=5, y=6) -&gt; '/d' and '/d/:x' and '/d/:x/:y'</pre>
+</div>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.path_shift">
+<tt class="descname">path_shift</tt><big>(</big><em>script_name</em>, <em>path_info</em>, <em>shift=1</em><big>)</big><a class="reference internal" href="_modules/bottle.html#path_shift"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.path_shift" title="Permalink to this definition">¶</a></dt>
+<dd><p>Shift path fragments from PATH_INFO to SCRIPT_NAME and vice versa.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Returns:</th><td class="field-body"><p class="first">The modified paths.</p>
+</td>
+</tr>
+<tr class="field-even field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>script_name</strong> &#8211; The SCRIPT_NAME path.</li>
+<li><strong>script_name</strong> &#8211; The PATH_INFO path.</li>
+<li><strong>shift</strong> &#8211; The number of path fragments to shift. May be negative to
+change the shift direction. (default: 1)</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+</dd></dl>
+
+</div>
+<div class="section" id="data-structures">
+<h3>Data Structures<a class="headerlink" href="#data-structures" title="Permalink to this headline">¶</a></h3>
+<dl class="class">
+<dt id="bottle.MultiDict">
+<em class="property">class </em><tt class="descname">MultiDict</tt><big>(</big><em>*a</em>, <em>**k</em><big>)</big><a class="reference internal" href="_modules/bottle.html#MultiDict"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.MultiDict" title="Permalink to this definition">¶</a></dt>
+<dd><p>This dict stores multiple values per key, but behaves exactly like a
+normal dict in that it returns only the newest value for any given key.
+There are special methods available to access the full list of values.</p>
+<dl class="method">
+<dt id="bottle.MultiDict.get">
+<tt class="descname">get</tt><big>(</big><em>key</em>, <em>default=None</em>, <em>index=-1</em>, <em>type=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#MultiDict.get"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.MultiDict.get" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the most recent value for a key.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>default</strong> &#8211; The default value to be returned if the key is not
+present or the type conversion fails.</li>
+<li><strong>index</strong> &#8211; An index for the list of available values.</li>
+<li><strong>type</strong> &#8211; If defined, this callable is used to cast the value
+into a specific type. Exception are suppressed and result in
+the default value to be returned.</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.MultiDict.append">
+<tt class="descname">append</tt><big>(</big><em>key</em>, <em>value</em><big>)</big><a class="reference internal" href="_modules/bottle.html#MultiDict.append"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.MultiDict.append" title="Permalink to this definition">¶</a></dt>
+<dd><p>Add a new value to the list of values for this key.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.MultiDict.replace">
+<tt class="descname">replace</tt><big>(</big><em>key</em>, <em>value</em><big>)</big><a class="reference internal" href="_modules/bottle.html#MultiDict.replace"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.MultiDict.replace" title="Permalink to this definition">¶</a></dt>
+<dd><p>Replace the list of values with a single value.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.MultiDict.getall">
+<tt class="descname">getall</tt><big>(</big><em>key</em><big>)</big><a class="reference internal" href="_modules/bottle.html#MultiDict.getall"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.MultiDict.getall" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return a (possibly empty) list of values for a key.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.MultiDict.getone">
+<tt class="descname">getone</tt><big>(</big><em>key</em>, <em>default=None</em>, <em>index=-1</em>, <em>type=None</em><big>)</big><a class="headerlink" href="#bottle.MultiDict.getone" title="Permalink to this definition">¶</a></dt>
+<dd><p>Aliases for WTForms to mimic other multi-dict APIs (Django)</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.MultiDict.getlist">
+<tt class="descname">getlist</tt><big>(</big><em>key</em><big>)</big><a class="headerlink" href="#bottle.MultiDict.getlist" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return a (possibly empty) list of values for a key.</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.HeaderDict">
+<em class="property">class </em><tt class="descname">HeaderDict</tt><big>(</big><em>*a</em>, <em>**ka</em><big>)</big><a class="reference internal" href="_modules/bottle.html#HeaderDict"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.HeaderDict" title="Permalink to this definition">¶</a></dt>
+<dd><p>A case-insensitive version of <a class="reference internal" href="#bottle.MultiDict" title="bottle.MultiDict"><tt class="xref py py-class docutils literal"><span class="pre">MultiDict</span></tt></a> that defaults to
+replace the old value instead of appending it.</p>
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.FormsDict">
+<em class="property">class </em><tt class="descname">FormsDict</tt><big>(</big><em>*a</em>, <em>**k</em><big>)</big><a class="reference internal" href="_modules/bottle.html#FormsDict"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.FormsDict" title="Permalink to this definition">¶</a></dt>
+<dd><p>This <a class="reference internal" href="#bottle.MultiDict" title="bottle.MultiDict"><tt class="xref py py-class docutils literal"><span class="pre">MultiDict</span></tt></a> subclass is used to store request form data.
+Additionally to the normal dict-like item access methods (which return
+unmodified data as native strings), this container also supports
+attribute-like access to its values. Attributes are automatically de-
+or recoded to match <a class="reference internal" href="#bottle.FormsDict.input_encoding" title="bottle.FormsDict.input_encoding"><tt class="xref py py-attr docutils literal"><span class="pre">input_encoding</span></tt></a> (default: &#8216;utf8&#8217;). Missing
+attributes default to an empty string.</p>
+<dl class="attribute">
+<dt id="bottle.FormsDict.input_encoding">
+<tt class="descname">input_encoding</tt><em class="property"> = 'utf8'</em><a class="headerlink" href="#bottle.FormsDict.input_encoding" title="Permalink to this definition">¶</a></dt>
+<dd><p>Encoding used for attribute values.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.FormsDict.recode_unicode">
+<tt class="descname">recode_unicode</tt><em class="property"> = True</em><a class="headerlink" href="#bottle.FormsDict.recode_unicode" title="Permalink to this definition">¶</a></dt>
+<dd><p>If true (default), unicode strings are first encoded with <cite>latin1</cite>
+and then decoded to match <a class="reference internal" href="#bottle.FormsDict.input_encoding" title="bottle.FormsDict.input_encoding"><tt class="xref py py-attr docutils literal"><span class="pre">input_encoding</span></tt></a>.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.FormsDict.decode">
+<tt class="descname">decode</tt><big>(</big><em>encoding=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#FormsDict.decode"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.FormsDict.decode" title="Permalink to this definition">¶</a></dt>
+<dd><p>Returns a copy with all keys and values de- or recoded to match
+<a class="reference internal" href="#bottle.FormsDict.input_encoding" title="bottle.FormsDict.input_encoding"><tt class="xref py py-attr docutils literal"><span class="pre">input_encoding</span></tt></a>. Some libraries (e.g. WTForms) want a
+unicode dictionary.</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.WSGIHeaderDict">
+<em class="property">class </em><tt class="descname">WSGIHeaderDict</tt><big>(</big><em>environ</em><big>)</big><a class="reference internal" href="_modules/bottle.html#WSGIHeaderDict"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.WSGIHeaderDict" title="Permalink to this definition">¶</a></dt>
+<dd><p>This dict-like class wraps a WSGI environ dict and provides convenient
+access to HTTP_* fields. Keys and values are native strings
+(2.x bytes or 3.x unicode) and keys are case-insensitive. If the WSGI
+environment contains non-native string values, these are de- or encoded
+using a lossless &#8216;latin1&#8217; character set.</p>
+<p>The API will remain stable even on changes to the relevant PEPs.
+Currently PEP 333, 444 and 3333 are supported. (PEP 444 is the only one
+that uses non-native strings.)</p>
+<dl class="attribute">
+<dt id="bottle.WSGIHeaderDict.cgikeys">
+<tt class="descname">cgikeys</tt><em class="property"> = ('CONTENT_TYPE', 'CONTENT_LENGTH')</em><a class="headerlink" href="#bottle.WSGIHeaderDict.cgikeys" title="Permalink to this definition">¶</a></dt>
+<dd><p>List of keys that do not have a <tt class="docutils literal"><span class="pre">HTTP_</span></tt> prefix.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.WSGIHeaderDict.raw">
+<tt class="descname">raw</tt><big>(</big><em>key</em>, <em>default=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#WSGIHeaderDict.raw"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.WSGIHeaderDict.raw" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the header value as is (may be bytes or unicode).</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.AppStack">
+<em class="property">class </em><tt class="descname">AppStack</tt><a class="reference internal" href="_modules/bottle.html#AppStack"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.AppStack" title="Permalink to this definition">¶</a></dt>
+<dd><p>A stack-like list. Calling it returns the head of the stack.</p>
+<dl class="method">
+<dt id="bottle.AppStack.pop">
+<tt class="descname">pop</tt><big>(</big><big>)</big><a class="headerlink" href="#bottle.AppStack.pop" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the current default application and remove it from the stack.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.AppStack.push">
+<tt class="descname">push</tt><big>(</big><em>value=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#AppStack.push"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.AppStack.push" title="Permalink to this definition">¶</a></dt>
+<dd><p>Add a new <a class="reference internal" href="#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> instance to the stack</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.ResourceManager">
+<em class="property">class </em><tt class="descname">ResourceManager</tt><big>(</big><em>base='./'</em>, <em>opener=&lt;built-in function open&gt;</em>, <em>cachemode='all'</em><big>)</big><a class="reference internal" href="_modules/bottle.html#ResourceManager"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.ResourceManager" title="Permalink to this definition">¶</a></dt>
+<dd><p>This class manages a list of search paths and helps to find and open
+application-bound resources (files).</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>base</strong> &#8211; default value for <a class="reference internal" href="#bottle.ResourceManager.add_path" title="bottle.ResourceManager.add_path"><tt class="xref py py-meth docutils literal"><span class="pre">add_path()</span></tt></a> calls.</li>
+<li><strong>opener</strong> &#8211; callable used to open resources.</li>
+<li><strong>cachemode</strong> &#8211; controls which lookups are cached. One of &#8216;all&#8217;,
+&#8216;found&#8217; or &#8216;none&#8217;.</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+<dl class="attribute">
+<dt id="bottle.ResourceManager.path">
+<tt class="descname">path</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.ResourceManager.path" title="Permalink to this definition">¶</a></dt>
+<dd><p>A list of search paths. See <a class="reference internal" href="#bottle.ResourceManager.add_path" title="bottle.ResourceManager.add_path"><tt class="xref py py-meth docutils literal"><span class="pre">add_path()</span></tt></a> for details.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.ResourceManager.cache">
+<tt class="descname">cache</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.ResourceManager.cache" title="Permalink to this definition">¶</a></dt>
+<dd><p>A cache for resolved paths. <tt class="docutils literal"><span class="pre">res.cache.clear()</span></tt> clears the cache.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.ResourceManager.add_path">
+<tt class="descname">add_path</tt><big>(</big><em>path</em>, <em>base=None</em>, <em>index=None</em>, <em>create=False</em><big>)</big><a class="reference internal" href="_modules/bottle.html#ResourceManager.add_path"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.ResourceManager.add_path" title="Permalink to this definition">¶</a></dt>
+<dd><p>Add a new path to the list of search paths. Return False if the
+path does not exist.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>path</strong> &#8211; The new search path. Relative paths are turned into
+an absolute and normalized form. If the path looks like a file
+(not ending in <cite>/</cite>), the filename is stripped off.</li>
+<li><strong>base</strong> &#8211; Path used to absolutize relative search paths.
+Defaults to <tt class="xref py py-attr docutils literal"><span class="pre">base</span></tt> which defaults to <tt class="docutils literal"><span class="pre">os.getcwd()</span></tt>.</li>
+<li><strong>index</strong> &#8211; Position within the list of search paths. Defaults
+to last index (appends to the list).</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+<p>The <cite>base</cite> parameter makes it easy to reference files installed
+along with a python module or package:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">res</span><span class="o">.</span><span class="n">add_path</span><span class="p">(</span><span class="s">&#39;./resources/&#39;</span><span class="p">,</span> <span class="n">__file__</span><span class="p">)</span>
+</pre></div>
+</div>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.ResourceManager.lookup">
+<tt class="descname">lookup</tt><big>(</big><em>name</em><big>)</big><a class="reference internal" href="_modules/bottle.html#ResourceManager.lookup"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.ResourceManager.lookup" title="Permalink to this definition">¶</a></dt>
+<dd><p>Search for a resource and return an absolute file path, or <cite>None</cite>.</p>
+<p>The <a class="reference internal" href="#bottle.ResourceManager.path" title="bottle.ResourceManager.path"><tt class="xref py py-attr docutils literal"><span class="pre">path</span></tt></a> list is searched in order. The first match is
+returend. Symlinks are followed. The result is cached to speed up
+future lookups.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.ResourceManager.open">
+<tt class="descname">open</tt><big>(</big><em>name</em>, <em>mode='r'</em>, <em>*args</em>, <em>**kwargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#ResourceManager.open"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.ResourceManager.open" title="Permalink to this definition">¶</a></dt>
+<dd><p>Find a resource and return a file object, or raise IOError.</p>
+</dd></dl>
+
+</dd></dl>
+
+</div>
+<div class="section" id="exceptions">
+<h3>Exceptions<a class="headerlink" href="#exceptions" title="Permalink to this headline">¶</a></h3>
+<dl class="exception">
+<dt id="bottle.BottleException">
+<em class="property">exception </em><tt class="descname">BottleException</tt><a class="reference internal" href="_modules/bottle.html#BottleException"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BottleException" title="Permalink to this definition">¶</a></dt>
+<dd><p>A base class for exceptions used by bottle.</p>
+</dd></dl>
+
+</div>
+</div>
+<div class="section" id="the-bottle-class">
+<h2>The <a class="reference internal" href="#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> Class<a class="headerlink" href="#the-bottle-class" title="Permalink to this headline">¶</a></h2>
+<dl class="class">
+<dt id="bottle.Bottle">
+<em class="property">class </em><tt class="descname">Bottle</tt><big>(</big><em>catchall=True</em>, <em>autojson=True</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle" title="Permalink to this definition">¶</a></dt>
+<dd><p>Each Bottle object represents a single, distinct web application and
+consists of routes, callbacks, plugins, resources and configuration.
+Instances are callable WSGI applications.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>catchall</strong> &#8211; If true (default), handle all exceptions. Turn off to
+let debugging middleware handle exceptions.</td>
+</tr>
+</tbody>
+</table>
+<dl class="attribute">
+<dt id="bottle.Bottle.catchall">
+<tt class="descname">catchall</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Bottle.catchall" title="Permalink to this definition">¶</a></dt>
+<dd><p>If true, most exceptions are caught and returned as <a class="reference internal" href="#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a></p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Bottle.resources">
+<tt class="descname">resources</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Bottle.resources" title="Permalink to this definition">¶</a></dt>
+<dd><p>A <a class="reference internal" href="#bottle.ResourceManager" title="bottle.ResourceManager"><tt class="xref py py-class docutils literal"><span class="pre">ResourceManager</span></tt></a> for application files</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Bottle.config">
+<tt class="descname">config</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Bottle.config" title="Permalink to this definition">¶</a></dt>
+<dd><p>A <tt class="xref py py-class docutils literal"><span class="pre">ConfigDict</span></tt> for app specific configuration.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.mount">
+<tt class="descname">mount</tt><big>(</big><em>prefix</em>, <em>app</em>, <em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.mount"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.mount" title="Permalink to this definition">¶</a></dt>
+<dd><p>Mount an application (<a class="reference internal" href="#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> or plain WSGI) to a specific
+URL prefix. Example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">root_app</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s">&#39;/admin/&#39;</span><span class="p">,</span> <span class="n">admin_app</span><span class="p">)</span>
+</pre></div>
+</div>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>prefix</strong> &#8211; path prefix or <cite>mount-point</cite>. If it ends in a slash,
+that slash is mandatory.</li>
+<li><strong>app</strong> &#8211; an instance of <a class="reference internal" href="#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> or a WSGI application.</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+<p>All other parameters are passed to the underlying <a class="reference internal" href="#bottle.route" title="bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">route()</span></tt></a> call.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.merge">
+<tt class="descname">merge</tt><big>(</big><em>routes</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.merge"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.merge" title="Permalink to this definition">¶</a></dt>
+<dd><p>Merge the routes of another <a class="reference internal" href="#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> application or a list of
+<a class="reference internal" href="#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> objects into this application. The routes keep their
+&#8216;owner&#8217;, meaning that the <a class="reference internal" href="#bottle.Route.app" title="bottle.Route.app"><tt class="xref py py-data docutils literal"><span class="pre">Route.app</span></tt></a> attribute is not
+changed.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.install">
+<tt class="descname">install</tt><big>(</big><em>plugin</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.install"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.install" title="Permalink to this definition">¶</a></dt>
+<dd><p>Add a plugin to the list of plugins and prepare it for being
+applied to all routes of this application. A plugin may be a simple
+decorator or an object that implements the <a class="reference internal" href="plugindev.html#bottle.Plugin" title="bottle.Plugin"><tt class="xref py py-class docutils literal"><span class="pre">Plugin</span></tt></a> API.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.uninstall">
+<tt class="descname">uninstall</tt><big>(</big><em>plugin</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.uninstall"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.uninstall" title="Permalink to this definition">¶</a></dt>
+<dd><p>Uninstall plugins. Pass an instance to remove a specific plugin, a type
+object to remove all plugins that match that type, a string to remove
+all plugins with a matching <tt class="docutils literal"><span class="pre">name</span></tt> attribute or <tt class="docutils literal"><span class="pre">True</span></tt> to remove all
+plugins. Return the list of removed plugins.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.run">
+<tt class="descname">run</tt><big>(</big><em>**kwargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.run"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.run" title="Permalink to this definition">¶</a></dt>
+<dd><p>Calls <a class="reference internal" href="#bottle.run" title="bottle.run"><tt class="xref py py-func docutils literal"><span class="pre">run()</span></tt></a> with the same parameters.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.reset">
+<tt class="descname">reset</tt><big>(</big><em>route=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.reset"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.reset" title="Permalink to this definition">¶</a></dt>
+<dd><p>Reset all routes (force plugins to be re-applied) and clear all
+caches. If an ID or route object is given, only that specific route
+is affected.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.close">
+<tt class="descname">close</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.close"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.close" title="Permalink to this definition">¶</a></dt>
+<dd><p>Close the application and all installed plugins.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.match">
+<tt class="descname">match</tt><big>(</big><em>environ</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.match"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.match" title="Permalink to this definition">¶</a></dt>
+<dd><p>Search for a matching route and return a (<a class="reference internal" href="#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> , urlargs)
+tuple. The second value is a dictionary with parameters extracted
+from the URL. Raise <a class="reference internal" href="#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> (404/405) on a non-match.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.get_url">
+<tt class="descname">get_url</tt><big>(</big><em>routename</em>, <em>**kargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.get_url"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.get_url" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return a string that matches a named route</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.add_route">
+<tt class="descname">add_route</tt><big>(</big><em>route</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.add_route"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.add_route" title="Permalink to this definition">¶</a></dt>
+<dd><p>Add a route object, but do not change the <a class="reference internal" href="#bottle.Route.app" title="bottle.Route.app"><tt class="xref py py-data docutils literal"><span class="pre">Route.app</span></tt></a>
+attribute.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.route">
+<tt class="descname">route</tt><big>(</big><em>path=None</em>, <em>method='GET'</em>, <em>callback=None</em>, <em>name=None</em>, <em>apply=None</em>, <em>skip=None</em>, <em>**config</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.route"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.route" title="Permalink to this definition">¶</a></dt>
+<dd><p>A decorator to bind a function to a request URL. Example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/hello/:name&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;Hello </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">name</span>
+</pre></div>
+</div>
+<p>The <tt class="docutils literal"><span class="pre">:name</span></tt> part is a wildcard. See <tt class="xref py py-class docutils literal"><span class="pre">Router</span></tt> for syntax
+details.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>path</strong> &#8211; Request path or a list of paths to listen to. If no
+path is specified, it is automatically generated from the
+signature of the function.</li>
+<li><strong>method</strong> &#8211; HTTP method (<cite>GET</cite>, <cite>POST</cite>, <cite>PUT</cite>, ...) or a list of
+methods to listen to. (default: <cite>GET</cite>)</li>
+<li><strong>callback</strong> &#8211; An optional shortcut to avoid the decorator
+syntax. <tt class="docutils literal"><span class="pre">route(...,</span> <span class="pre">callback=func)</span></tt> equals <tt class="docutils literal"><span class="pre">route(...)(func)</span></tt></li>
+<li><strong>name</strong> &#8211; The name for this route. (default: None)</li>
+<li><strong>apply</strong> &#8211; A decorator or plugin or a list of plugins. These are
+applied to the route callback in addition to installed plugins.</li>
+<li><strong>skip</strong> &#8211; A list of plugins, plugin classes or names. Matching
+plugins are not installed to this route. <tt class="docutils literal"><span class="pre">True</span></tt> skips all.</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+<p>Any additional keyword arguments are stored as route-specific
+configuration and passed to plugins (see <a class="reference internal" href="plugindev.html#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.apply()</span></tt></a>).</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.get">
+<tt class="descname">get</tt><big>(</big><em>path=None</em>, <em>method='GET'</em>, <em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.get"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.get" title="Permalink to this definition">¶</a></dt>
+<dd><p>Equals <a class="reference internal" href="#bottle.route" title="bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">route()</span></tt></a>.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.post">
+<tt class="descname">post</tt><big>(</big><em>path=None</em>, <em>method='POST'</em>, <em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.post"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.post" title="Permalink to this definition">¶</a></dt>
+<dd><p>Equals <a class="reference internal" href="#bottle.route" title="bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">route()</span></tt></a> with a <tt class="docutils literal"><span class="pre">POST</span></tt> method parameter.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.put">
+<tt class="descname">put</tt><big>(</big><em>path=None</em>, <em>method='PUT'</em>, <em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.put"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.put" title="Permalink to this definition">¶</a></dt>
+<dd><p>Equals <a class="reference internal" href="#bottle.route" title="bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">route()</span></tt></a> with a <tt class="docutils literal"><span class="pre">PUT</span></tt> method parameter.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.delete">
+<tt class="descname">delete</tt><big>(</big><em>path=None</em>, <em>method='DELETE'</em>, <em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.delete"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.delete" title="Permalink to this definition">¶</a></dt>
+<dd><p>Equals <a class="reference internal" href="#bottle.route" title="bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">route()</span></tt></a> with a <tt class="docutils literal"><span class="pre">DELETE</span></tt> method parameter.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.error">
+<tt class="descname">error</tt><big>(</big><em>code=500</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.error"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.error" title="Permalink to this definition">¶</a></dt>
+<dd><p>Decorator: Register an output handler for a HTTP error code</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.hook">
+<tt class="descname">hook</tt><big>(</big><em>name</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.hook"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.hook" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return a decorator that attaches a callback to a hook. Three hooks
+are currently implemented:</p>
+<ul class="simple">
+<li>before_request: Executed once before each request</li>
+<li>after_request: Executed once after each request</li>
+<li>app_reset: Called whenever <a class="reference internal" href="#bottle.Bottle.reset" title="bottle.Bottle.reset"><tt class="xref py py-meth docutils literal"><span class="pre">reset()</span></tt></a> is called.</li>
+</ul>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.handle">
+<tt class="descname">handle</tt><big>(</big><em>path</em>, <em>method='GET'</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.handle"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.handle" title="Permalink to this definition">¶</a></dt>
+<dd><p>(deprecated) Execute the first matching route callback and return
+the result. <a class="reference internal" href="#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> exceptions are caught and returned.
+If <a class="reference internal" href="#bottle.Bottle.catchall" title="bottle.Bottle.catchall"><tt class="xref py py-attr docutils literal"><span class="pre">Bottle.catchall</span></tt></a> is true, other exceptions are caught as
+well and returned as <a class="reference internal" href="#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> instances (500).</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Bottle.wsgi">
+<tt class="descname">wsgi</tt><big>(</big><em>environ</em>, <em>start_response</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Bottle.wsgi"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Bottle.wsgi" title="Permalink to this definition">¶</a></dt>
+<dd><p>The bottle WSGI-interface.</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.Route">
+<em class="property">class </em><tt class="descname">Route</tt><big>(</big><em>app</em>, <em>rule</em>, <em>method</em>, <em>callback</em>, <em>name=None</em>, <em>plugins=None</em>, <em>skiplist=None</em>, <em>**config</em><big>)</big><a class="reference internal" href="_modules/bottle.html#Route"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Route" title="Permalink to this definition">¶</a></dt>
+<dd><p>This class wraps a route callback along with route specific metadata and
+configuration and applies Plugins on demand. It is also responsible for
+turing an URL path rule into a regular expression usable by the Router.</p>
+<dl class="attribute">
+<dt id="bottle.Route.app">
+<tt class="descname">app</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.app" title="Permalink to this definition">¶</a></dt>
+<dd><p>The application this route is installed to.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.rule">
+<tt class="descname">rule</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.rule" title="Permalink to this definition">¶</a></dt>
+<dd><p>The path-rule string (e.g. <tt class="docutils literal"><span class="pre">/wiki/:page</span></tt>).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.method">
+<tt class="descname">method</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.method" title="Permalink to this definition">¶</a></dt>
+<dd><p>The HTTP method as a string (e.g. <tt class="docutils literal"><span class="pre">GET</span></tt>).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.callback">
+<tt class="descname">callback</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.callback" title="Permalink to this definition">¶</a></dt>
+<dd><p>The original callback with no plugins applied. Useful for introspection.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.name">
+<tt class="descname">name</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.name" title="Permalink to this definition">¶</a></dt>
+<dd><p>The name of the route (if specified) or <tt class="docutils literal"><span class="pre">None</span></tt>.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.plugins">
+<tt class="descname">plugins</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.plugins" title="Permalink to this definition">¶</a></dt>
+<dd><p>A list of route-specific plugins (see <a class="reference internal" href="#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a>).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.skiplist">
+<tt class="descname">skiplist</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.skiplist" title="Permalink to this definition">¶</a></dt>
+<dd><p>A list of plugins to not apply to this route (see <a class="reference internal" href="#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a>).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Route.config">
+<tt class="descname">config</tt><em class="property"> = None</em><a class="headerlink" href="#bottle.Route.config" title="Permalink to this definition">¶</a></dt>
+<dd><p>Additional keyword arguments passed to the <a class="reference internal" href="#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a>
+decorator are stored in this dictionary. Used for route-specific
+plugin configuration and meta-data.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Route.reset">
+<tt class="descname">reset</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#Route.reset"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Route.reset" title="Permalink to this definition">¶</a></dt>
+<dd><p>Forget any cached values. The next time <tt class="xref py py-attr docutils literal"><span class="pre">call</span></tt> is accessed,
+all plugins are re-applied.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Route.prepare">
+<tt class="descname">prepare</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#Route.prepare"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Route.prepare" title="Permalink to this definition">¶</a></dt>
+<dd><p>Do all on-demand work immediately (useful for debugging).</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Route.all_plugins">
+<tt class="descname">all_plugins</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#Route.all_plugins"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.Route.all_plugins" title="Permalink to this definition">¶</a></dt>
+<dd><p>Yield all Plugins affecting this route.</p>
+</dd></dl>
+
+</dd></dl>
+
+</div>
+<div class="section" id="the-request-object">
+<h2>The <a class="reference internal" href="#bottle.Request" title="bottle.Request"><tt class="xref py py-class docutils literal"><span class="pre">Request</span></tt></a> Object<a class="headerlink" href="#the-request-object" title="Permalink to this headline">¶</a></h2>
+<p>The <a class="reference internal" href="#bottle.Request" title="bottle.Request"><tt class="xref py py-class docutils literal"><span class="pre">Request</span></tt></a> class wraps a WSGI environment and provides helpful methods to parse and access form data, cookies, file uploads and other metadata. Most of the attributes are read-only.</p>
+<dl class="attribute">
+<dt id="bottle.Request">
+<tt class="descname">Request</tt><a class="headerlink" href="#bottle.Request" title="Permalink to this definition">¶</a></dt>
+<dd><p>alias of <a class="reference internal" href="#bottle.BaseRequest" title="bottle.BaseRequest"><tt class="xref py py-class docutils literal"><span class="pre">BaseRequest</span></tt></a></p>
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.BaseRequest">
+<em class="property">class </em><tt class="descname">BaseRequest</tt><big>(</big><em>environ=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseRequest"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest" title="Permalink to this definition">¶</a></dt>
+<dd><p>A wrapper for WSGI environment dictionaries that adds a lot of
+convenient access methods and properties. Most of them are read-only.</p>
+<p>Adding new attributes to a request actually adds them to the environ
+dictionary (as &#8216;bottle.request.ext.&lt;name&gt;&#8217;). This is the recommended
+way to store and access request-specific data.</p>
+<dl class="attribute">
+<dt id="bottle.BaseRequest.MEMFILE_MAX">
+<tt class="descname">MEMFILE_MAX</tt><em class="property"> = 102400</em><a class="headerlink" href="#bottle.BaseRequest.MEMFILE_MAX" title="Permalink to this definition">¶</a></dt>
+<dd><p>Maximum size of memory buffer for <a class="reference internal" href="#bottle.BaseRequest.body" title="bottle.BaseRequest.body"><tt class="xref py py-attr docutils literal"><span class="pre">body</span></tt></a> in bytes.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.MAX_PARAMS">
+<tt class="descname">MAX_PARAMS</tt><em class="property"> = 100</em><a class="headerlink" href="#bottle.BaseRequest.MAX_PARAMS" title="Permalink to this definition">¶</a></dt>
+<dd><p>Maximum number pr GET or POST parameters per request</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.environ">
+<tt class="descname">environ</tt><a class="headerlink" href="#bottle.BaseRequest.environ" title="Permalink to this definition">¶</a></dt>
+<dd><p>The wrapped WSGI environ dictionary. This is the only real attribute.
+All other attributes actually are read-only properties.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.app">
+<tt class="descname">app</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.app"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.app" title="Permalink to this definition">¶</a></dt>
+<dd><p>Bottle application handling this request.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.path">
+<tt class="descname">path</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.path"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.path" title="Permalink to this definition">¶</a></dt>
+<dd><p>The value of <tt class="docutils literal"><span class="pre">PATH_INFO</span></tt> with exactly one prefixed slash (to fix
+broken clients and avoid the &#8220;empty path&#8221; edge case).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.method">
+<tt class="descname">method</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.method"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.method" title="Permalink to this definition">¶</a></dt>
+<dd><p>The <tt class="docutils literal"><span class="pre">REQUEST_METHOD</span></tt> value as an uppercase string.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.headers">
+<tt class="descname">headers</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.headers"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.headers" title="Permalink to this definition">¶</a></dt>
+<dd><p>A <a class="reference internal" href="#bottle.WSGIHeaderDict" title="bottle.WSGIHeaderDict"><tt class="xref py py-class docutils literal"><span class="pre">WSGIHeaderDict</span></tt></a> that provides case-insensitive access to
+HTTP request headers.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseRequest.get_header">
+<tt class="descname">get_header</tt><big>(</big><em>name</em>, <em>default=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseRequest.get_header"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.get_header" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the value of a request header, or a given default value.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.cookies">
+<tt class="descname">cookies</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.cookies"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.cookies" title="Permalink to this definition">¶</a></dt>
+<dd><p>Cookies parsed into a <a class="reference internal" href="#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a>. Signed cookies are NOT
+decoded. Use <a class="reference internal" href="#bottle.BaseRequest.get_cookie" title="bottle.BaseRequest.get_cookie"><tt class="xref py py-meth docutils literal"><span class="pre">get_cookie()</span></tt></a> if you expect signed cookies.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseRequest.get_cookie">
+<tt class="descname">get_cookie</tt><big>(</big><em>key</em>, <em>default=None</em>, <em>secret=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseRequest.get_cookie"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.get_cookie" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the content of a cookie. To read a <cite>Signed Cookie</cite>, the
+<cite>secret</cite> must match the one used to create the cookie (see
+<a class="reference internal" href="#bottle.BaseResponse.set_cookie" title="bottle.BaseResponse.set_cookie"><tt class="xref py py-meth docutils literal"><span class="pre">BaseResponse.set_cookie()</span></tt></a>). If anything goes wrong (missing
+cookie or wrong signature), return a default value.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.query">
+<tt class="descname">query</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.query"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.query" title="Permalink to this definition">¶</a></dt>
+<dd><p>The <a class="reference internal" href="#bottle.BaseRequest.query_string" title="bottle.BaseRequest.query_string"><tt class="xref py py-attr docutils literal"><span class="pre">query_string</span></tt></a> parsed into a <a class="reference internal" href="#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a>. These
+values are sometimes called &#8220;URL arguments&#8221; or &#8220;GET parameters&#8221;, but
+not to be confused with &#8220;URL wildcards&#8221; as they are provided by the
+<tt class="xref py py-class docutils literal"><span class="pre">Router</span></tt>.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.forms">
+<tt class="descname">forms</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.forms"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.forms" title="Permalink to this definition">¶</a></dt>
+<dd><p>Form values parsed from an <cite>url-encoded</cite> or <cite>multipart/form-data</cite>
+encoded POST or PUT request body. The result is retuned as a
+<a class="reference internal" href="#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a>. All keys and values are strings. File uploads
+are stored separately in <a class="reference internal" href="#bottle.BaseRequest.files" title="bottle.BaseRequest.files"><tt class="xref py py-attr docutils literal"><span class="pre">files</span></tt></a>.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.params">
+<tt class="descname">params</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.params"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.params" title="Permalink to this definition">¶</a></dt>
+<dd><p>A <a class="reference internal" href="#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a> with the combined values of <a class="reference internal" href="#bottle.BaseRequest.query" title="bottle.BaseRequest.query"><tt class="xref py py-attr docutils literal"><span class="pre">query</span></tt></a> and
+<a class="reference internal" href="#bottle.BaseRequest.forms" title="bottle.BaseRequest.forms"><tt class="xref py py-attr docutils literal"><span class="pre">forms</span></tt></a>. File uploads are stored in <a class="reference internal" href="#bottle.BaseRequest.files" title="bottle.BaseRequest.files"><tt class="xref py py-attr docutils literal"><span class="pre">files</span></tt></a>.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.files">
+<tt class="descname">files</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.files"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.files" title="Permalink to this definition">¶</a></dt>
+<dd><p>File uploads parsed from an <cite>url-encoded</cite> or <cite>multipart/form-data</cite>
+encoded POST or PUT request body. The values are instances of
+<tt class="xref py py-class docutils literal"><span class="pre">cgi.FieldStorage</span></tt>. The most important attributes are:</p>
+<dl class="docutils">
+<dt>filename</dt>
+<dd>The filename, if specified; otherwise None; this is the client
+side filename, <em>not</em> the file name on which it is stored (that&#8217;s
+a temporary file you don&#8217;t deal with)</dd>
+<dt>file</dt>
+<dd>The file(-like) object from which you can read the data.</dd>
+<dt>value</dt>
+<dd>The value as a <em>string</em>; for file uploads, this transparently
+reads the file every time you request the value. Do not do this
+on big files.</dd>
+</dl>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.json">
+<tt class="descname">json</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.json"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.json" title="Permalink to this definition">¶</a></dt>
+<dd><p>If the <tt class="docutils literal"><span class="pre">Content-Type</span></tt> header is <tt class="docutils literal"><span class="pre">application/json</span></tt>, this
+property holds the parsed content of the request body. Only requests
+smaller than <a class="reference internal" href="#bottle.BaseRequest.MEMFILE_MAX" title="bottle.BaseRequest.MEMFILE_MAX"><tt class="xref py py-attr docutils literal"><span class="pre">MEMFILE_MAX</span></tt></a> are processed to avoid memory
+exhaustion.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.body">
+<tt class="descname">body</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.body"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.body" title="Permalink to this definition">¶</a></dt>
+<dd><p>The HTTP request body as a seek-able file-like object. Depending on
+<a class="reference internal" href="#bottle.BaseRequest.MEMFILE_MAX" title="bottle.BaseRequest.MEMFILE_MAX"><tt class="xref py py-attr docutils literal"><span class="pre">MEMFILE_MAX</span></tt></a>, this is either a temporary file or a
+<a class="reference external" href="http://docs.python.org/library/io.html#io.BytesIO" title="(in Python v2.7)"><tt class="xref py py-class docutils literal"><span class="pre">io.BytesIO</span></tt></a> instance. Accessing this property for the first
+time reads and replaces the <tt class="docutils literal"><span class="pre">wsgi.input</span></tt> environ variable.
+Subsequent accesses just do a <cite>seek(0)</cite> on the file object.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.GET">
+<tt class="descname">GET</tt><a class="headerlink" href="#bottle.BaseRequest.GET" title="Permalink to this definition">¶</a></dt>
+<dd><p>An alias for <a class="reference internal" href="#bottle.BaseRequest.query" title="bottle.BaseRequest.query"><tt class="xref py py-attr docutils literal"><span class="pre">query</span></tt></a>.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.POST">
+<tt class="descname">POST</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.POST"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.POST" title="Permalink to this definition">¶</a></dt>
+<dd><p>The values of <a class="reference internal" href="#bottle.BaseRequest.forms" title="bottle.BaseRequest.forms"><tt class="xref py py-attr docutils literal"><span class="pre">forms</span></tt></a> and <a class="reference internal" href="#bottle.BaseRequest.files" title="bottle.BaseRequest.files"><tt class="xref py py-attr docutils literal"><span class="pre">files</span></tt></a> combined into a single
+<a class="reference internal" href="#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a>. Values are either strings (form values) or
+instances of <tt class="xref py py-class docutils literal"><span class="pre">cgi.FieldStorage</span></tt> (file uploads).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.COOKIES">
+<tt class="descname">COOKIES</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.COOKIES"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.COOKIES" title="Permalink to this definition">¶</a></dt>
+<dd><p>Alias for <a class="reference internal" href="#bottle.BaseRequest.cookies" title="bottle.BaseRequest.cookies"><tt class="xref py py-attr docutils literal"><span class="pre">cookies</span></tt></a> (deprecated).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.url">
+<tt class="descname">url</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.url"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.url" title="Permalink to this definition">¶</a></dt>
+<dd><p>The full request URI including hostname and scheme. If your app
+lives behind a reverse proxy or load balancer and you get confusing
+results, make sure that the <tt class="docutils literal"><span class="pre">X-Forwarded-Host</span></tt> header is set
+correctly.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.urlparts">
+<tt class="descname">urlparts</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.urlparts"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.urlparts" title="Permalink to this definition">¶</a></dt>
+<dd><p>The <a class="reference internal" href="#bottle.BaseRequest.url" title="bottle.BaseRequest.url"><tt class="xref py py-attr docutils literal"><span class="pre">url</span></tt></a> string as an <a class="reference external" href="http://docs.python.org/library/urlparse.html#urlparse.SplitResult" title="(in Python v2.7)"><tt class="xref py py-class docutils literal"><span class="pre">urlparse.SplitResult</span></tt></a> tuple.
+The tuple contains (scheme, host, path, query_string and fragment),
+but the fragment is always empty because it is not visible to the
+server.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.fullpath">
+<tt class="descname">fullpath</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.fullpath"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.fullpath" title="Permalink to this definition">¶</a></dt>
+<dd><p>Request path including <a class="reference internal" href="#bottle.BaseRequest.script_name" title="bottle.BaseRequest.script_name"><tt class="xref py py-attr docutils literal"><span class="pre">script_name</span></tt></a> (if present).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.query_string">
+<tt class="descname">query_string</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.query_string"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.query_string" title="Permalink to this definition">¶</a></dt>
+<dd><p>The raw <a class="reference internal" href="#bottle.BaseRequest.query" title="bottle.BaseRequest.query"><tt class="xref py py-attr docutils literal"><span class="pre">query</span></tt></a> part of the URL (everything in between <tt class="docutils literal"><span class="pre">?</span></tt>
+and <tt class="docutils literal"><span class="pre">#</span></tt>) as a string.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.script_name">
+<tt class="descname">script_name</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.script_name"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.script_name" title="Permalink to this definition">¶</a></dt>
+<dd><p>The initial portion of the URL&#8217;s <cite>path</cite> that was removed by a higher
+level (server or routing middleware) before the application was
+called. This script path is returned with leading and tailing
+slashes.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseRequest.path_shift">
+<tt class="descname">path_shift</tt><big>(</big><em>shift=1</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseRequest.path_shift"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.path_shift" title="Permalink to this definition">¶</a></dt>
+<dd><p>Shift path segments from <a class="reference internal" href="#bottle.BaseRequest.path" title="bottle.BaseRequest.path"><tt class="xref py py-attr docutils literal"><span class="pre">path</span></tt></a> to <a class="reference internal" href="#bottle.BaseRequest.script_name" title="bottle.BaseRequest.script_name"><tt class="xref py py-attr docutils literal"><span class="pre">script_name</span></tt></a> and
+vice versa.</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><strong>shift</strong> &#8211; The number of path segments to shift. May be negative
+to change the shift direction. (default: 1)</td>
+</tr>
+</tbody>
+</table>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.content_length">
+<tt class="descname">content_length</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.content_length"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.content_length" title="Permalink to this definition">¶</a></dt>
+<dd><p>The request body length as an integer. The client is responsible to
+set this header. Otherwise, the real length of the body is unknown
+and -1 is returned. In this case, <a class="reference internal" href="#bottle.BaseRequest.body" title="bottle.BaseRequest.body"><tt class="xref py py-attr docutils literal"><span class="pre">body</span></tt></a> will be empty.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.content_type">
+<tt class="descname">content_type</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.content_type"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.content_type" title="Permalink to this definition">¶</a></dt>
+<dd><p>The Content-Type header as a lowercase-string (default: empty).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.is_xhr">
+<tt class="descname">is_xhr</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.is_xhr"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.is_xhr" title="Permalink to this definition">¶</a></dt>
+<dd><p>True if the request was triggered by a XMLHttpRequest. This only
+works with JavaScript libraries that support the <cite>X-Requested-With</cite>
+header (most of the popular libraries do).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.is_ajax">
+<tt class="descname">is_ajax</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.is_ajax"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.is_ajax" title="Permalink to this definition">¶</a></dt>
+<dd><p>Alias for <a class="reference internal" href="#bottle.BaseRequest.is_xhr" title="bottle.BaseRequest.is_xhr"><tt class="xref py py-attr docutils literal"><span class="pre">is_xhr</span></tt></a>. &#8220;Ajax&#8221; is not the right term.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.auth">
+<tt class="descname">auth</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.auth"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.auth" title="Permalink to this definition">¶</a></dt>
+<dd><p>HTTP authentication data as a (user, password) tuple. This
+implementation currently supports basic (not digest) authentication
+only. If the authentication happened at a higher level (e.g. in the
+front web-server or a middleware), the password field is None, but
+the user field is looked up from the <tt class="docutils literal"><span class="pre">REMOTE_USER</span></tt> environ
+variable. On any errors, None is returned.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.remote_route">
+<tt class="descname">remote_route</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.remote_route"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.remote_route" title="Permalink to this definition">¶</a></dt>
+<dd><p>A list of all IPs that were involved in this request, starting with
+the client IP and followed by zero or more proxies. This does only
+work if all proxies support the <tt class="docutils literal"><span class="pre">`X-Forwarded-For</span></tt> header. Note
+that this information can be forged by malicious clients.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseRequest.remote_addr">
+<tt class="descname">remote_addr</tt><a class="reference internal" href="_modules/bottle.html#BaseRequest.remote_addr"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.remote_addr" title="Permalink to this definition">¶</a></dt>
+<dd><p>The client IP as a string. Note that this information can be forged
+by malicious clients.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseRequest.copy">
+<tt class="descname">copy</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseRequest.copy"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseRequest.copy" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return a new <a class="reference internal" href="#bottle.Request" title="bottle.Request"><tt class="xref py py-class docutils literal"><span class="pre">Request</span></tt></a> with a shallow <a class="reference internal" href="#bottle.BaseRequest.environ" title="bottle.BaseRequest.environ"><tt class="xref py py-attr docutils literal"><span class="pre">environ</span></tt></a> copy.</p>
+</dd></dl>
+
+</dd></dl>
+
+<p>The module-level <a class="reference internal" href="#bottle.request" title="bottle.request"><tt class="xref py py-data docutils literal"><span class="pre">bottle.request</span></tt></a> is a proxy object (implemented in <a class="reference internal" href="#bottle.LocalRequest" title="bottle.LocalRequest"><tt class="xref py py-class docutils literal"><span class="pre">LocalRequest</span></tt></a>) and always refers to the <cite>current</cite> request, or in other words, the request that is currently processed by the request handler in the current thread. This <cite>thread locality</cite> ensures that you can safely use a global instance in a multi-threaded environment.</p>
+<dl class="class">
+<dt id="bottle.LocalRequest">
+<em class="property">class </em><tt class="descname">LocalRequest</tt><big>(</big><em>environ=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#LocalRequest"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.LocalRequest" title="Permalink to this definition">¶</a></dt>
+<dd><p>A thread-local subclass of <a class="reference internal" href="#bottle.BaseRequest" title="bottle.BaseRequest"><tt class="xref py py-class docutils literal"><span class="pre">BaseRequest</span></tt></a> with a different
+set of attribues for each thread. There is usually only one global
+instance of this class (<a class="reference internal" href="#bottle.request" title="bottle.request"><tt class="xref py py-data docutils literal"><span class="pre">request</span></tt></a>). If accessed during a
+request/response cycle, this instance always refers to the <em>current</em>
+request (even on a multithreaded server).</p>
+<dl class="method">
+<dt id="bottle.LocalRequest.bind">
+<tt class="descname">bind</tt><big>(</big><em>environ=None</em><big>)</big><a class="headerlink" href="#bottle.LocalRequest.bind" title="Permalink to this definition">¶</a></dt>
+<dd><p>Wrap a WSGI environ dictionary.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.LocalRequest.environ">
+<tt class="descname">environ</tt><a class="headerlink" href="#bottle.LocalRequest.environ" title="Permalink to this definition">¶</a></dt>
+<dd><p>Thread-local property stored in <tt class="xref py py-data docutils literal"><span class="pre">_lctx.request_environ</span></tt></p>
+</dd></dl>
+
+</dd></dl>
+
+</div>
+<div class="section" id="the-response-object">
+<h2>The <a class="reference internal" href="#bottle.Response" title="bottle.Response"><tt class="xref py py-class docutils literal"><span class="pre">Response</span></tt></a> Object<a class="headerlink" href="#the-response-object" title="Permalink to this headline">¶</a></h2>
+<p>The <a class="reference internal" href="#bottle.Response" title="bottle.Response"><tt class="xref py py-class docutils literal"><span class="pre">Response</span></tt></a> class stores the HTTP status code as well as headers and cookies that are to be sent to the client. Similar to <a class="reference internal" href="#bottle.request" title="bottle.request"><tt class="xref py py-data docutils literal"><span class="pre">bottle.request</span></tt></a> there is a thread-local <a class="reference internal" href="#bottle.response" title="bottle.response"><tt class="xref py py-data docutils literal"><span class="pre">bottle.response</span></tt></a> instance that can be used to adjust the <cite>current</cite> response. Moreover, you can instantiate <a class="reference internal" href="#bottle.Response" title="bottle.Response"><tt class="xref py py-class docutils literal"><span class="pre">Response</span></tt></a> and return it from your request handler. In this case, the custom instance overrules the headers and cookies defined in the global one.</p>
+<dl class="attribute">
+<dt id="bottle.Response">
+<tt class="descname">Response</tt><a class="headerlink" href="#bottle.Response" title="Permalink to this definition">¶</a></dt>
+<dd><p>alias of <a class="reference internal" href="#bottle.BaseResponse" title="bottle.BaseResponse"><tt class="xref py py-class docutils literal"><span class="pre">BaseResponse</span></tt></a></p>
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.BaseResponse">
+<em class="property">class </em><tt class="descname">BaseResponse</tt><big>(</big><em>body=''</em>, <em>status=None</em>, <em>**headers</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse" title="Permalink to this definition">¶</a></dt>
+<dd><p>Storage class for a response body as well as headers and cookies.</p>
+<p>This class does support dict-like case-insensitive item-access to
+headers, but is NOT a dict. Most notably, iterating over a response
+yields parts of the body and not the headers.</p>
+<dl class="method">
+<dt id="bottle.BaseResponse.copy">
+<tt class="descname">copy</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.copy"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.copy" title="Permalink to this definition">¶</a></dt>
+<dd><p>Returns a copy of self.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.status_line">
+<tt class="descname">status_line</tt><a class="reference internal" href="_modules/bottle.html#BaseResponse.status_line"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.status_line" title="Permalink to this definition">¶</a></dt>
+<dd><p>The HTTP status line as a string (e.g. <tt class="docutils literal"><span class="pre">404</span> <span class="pre">Not</span> <span class="pre">Found</span></tt>).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.status_code">
+<tt class="descname">status_code</tt><a class="reference internal" href="_modules/bottle.html#BaseResponse.status_code"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.status_code" title="Permalink to this definition">¶</a></dt>
+<dd><p>The HTTP status code as an integer (e.g. 404).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.status">
+<tt class="descname">status</tt><a class="headerlink" href="#bottle.BaseResponse.status" title="Permalink to this definition">¶</a></dt>
+<dd><p>A writeable property to change the HTTP response status. It accepts
+either a numeric code (100-999) or a string with a custom reason
+phrase (e.g. &#8220;404 Brain not found&#8221;). Both <a class="reference internal" href="#bottle.BaseResponse.status_line" title="bottle.BaseResponse.status_line"><tt class="xref py py-data docutils literal"><span class="pre">status_line</span></tt></a> and
+<a class="reference internal" href="#bottle.BaseResponse.status_code" title="bottle.BaseResponse.status_code"><tt class="xref py py-data docutils literal"><span class="pre">status_code</span></tt></a> are updated accordingly. The return value is
+always a status string.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.headers">
+<tt class="descname">headers</tt><a class="reference internal" href="_modules/bottle.html#BaseResponse.headers"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.headers" title="Permalink to this definition">¶</a></dt>
+<dd><p>An instance of <a class="reference internal" href="#bottle.HeaderDict" title="bottle.HeaderDict"><tt class="xref py py-class docutils literal"><span class="pre">HeaderDict</span></tt></a>, a case-insensitive dict-like
+view on the response headers.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseResponse.get_header">
+<tt class="descname">get_header</tt><big>(</big><em>name</em>, <em>default=None</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.get_header"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.get_header" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the value of a previously defined header. If there is no
+header with that name, return a default value.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseResponse.set_header">
+<tt class="descname">set_header</tt><big>(</big><em>name</em>, <em>value</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.set_header"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.set_header" title="Permalink to this definition">¶</a></dt>
+<dd><p>Create a new response header, replacing any previously defined
+headers with the same name.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseResponse.add_header">
+<tt class="descname">add_header</tt><big>(</big><em>name</em>, <em>value</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.add_header"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.add_header" title="Permalink to this definition">¶</a></dt>
+<dd><p>Add an additional response header, not removing duplicates.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseResponse.iter_headers">
+<tt class="descname">iter_headers</tt><big>(</big><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.iter_headers"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.iter_headers" title="Permalink to this definition">¶</a></dt>
+<dd><p>Yield (header, value) tuples, skipping headers that are not
+allowed with the current response status code.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.headerlist">
+<tt class="descname">headerlist</tt><a class="reference internal" href="_modules/bottle.html#BaseResponse.headerlist"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.headerlist" title="Permalink to this definition">¶</a></dt>
+<dd><p>WSGI conform list of (header, value) tuples.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.content_type">
+<tt class="descname">content_type</tt><a class="headerlink" href="#bottle.BaseResponse.content_type" title="Permalink to this definition">¶</a></dt>
+<dd><p>Current value of the &#8216;Content-Type&#8217; header.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.content_length">
+<tt class="descname">content_length</tt><a class="headerlink" href="#bottle.BaseResponse.content_length" title="Permalink to this definition">¶</a></dt>
+<dd><p>Current value of the &#8216;Content-Length&#8217; header.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.charset">
+<tt class="descname">charset</tt><a class="reference internal" href="_modules/bottle.html#BaseResponse.charset"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.charset" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the charset specified in the content-type header (default: utf8).</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.BaseResponse.COOKIES">
+<tt class="descname">COOKIES</tt><a class="reference internal" href="_modules/bottle.html#BaseResponse.COOKIES"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.COOKIES" title="Permalink to this definition">¶</a></dt>
+<dd><p>A dict-like SimpleCookie instance. This should not be used directly.
+See <a class="reference internal" href="#bottle.BaseResponse.set_cookie" title="bottle.BaseResponse.set_cookie"><tt class="xref py py-meth docutils literal"><span class="pre">set_cookie()</span></tt></a>.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseResponse.set_cookie">
+<tt class="descname">set_cookie</tt><big>(</big><em>name</em>, <em>value</em>, <em>secret=None</em>, <em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.set_cookie"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.set_cookie" title="Permalink to this definition">¶</a></dt>
+<dd><p>Create a new cookie or replace an old one. If the <cite>secret</cite> parameter is
+set, create a <cite>Signed Cookie</cite> (described below).</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>name</strong> &#8211; the name of the cookie.</li>
+<li><strong>value</strong> &#8211; the value of the cookie.</li>
+<li><strong>secret</strong> &#8211; a signature key required for signed cookies.</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+<p>Additionally, this method accepts all RFC 2109 attributes that are
+supported by <tt class="xref py py-class docutils literal"><span class="pre">cookie.Morsel</span></tt>, including:</p>
+<table class="docutils field-list" frame="void" rules="none">
+<col class="field-name" />
+<col class="field-body" />
+<tbody valign="top">
+<tr class="field-odd field"><th class="field-name">Parameters:</th><td class="field-body"><ul class="first last simple">
+<li><strong>max_age</strong> &#8211; maximum age in seconds. (default: None)</li>
+<li><strong>expires</strong> &#8211; a datetime object or UNIX timestamp. (default: None)</li>
+<li><strong>domain</strong> &#8211; the domain that is allowed to read the cookie.
+(default: current domain)</li>
+<li><strong>path</strong> &#8211; limits the cookie to a given path (default: current path)</li>
+<li><strong>secure</strong> &#8211; limit the cookie to HTTPS connections (default: off).</li>
+<li><strong>httponly</strong> &#8211; prevents client-side javascript to read this cookie
+(default: off, requires Python 2.6 or newer).</li>
+</ul>
+</td>
+</tr>
+</tbody>
+</table>
+<p>If neither <cite>expires</cite> nor <cite>max_age</cite> is set (default), the cookie will
+expire at the end of the browser session (as soon as the browser
+window is closed).</p>
+<p>Signed cookies may store any pickle-able object and are
+cryptographically signed to prevent manipulation. Keep in mind that
+cookies are limited to 4kb in most browsers.</p>
+<p>Warning: Signed cookies are not encrypted (the client can still see
+the content) and not copy-protected (the client can restore an old
+cookie). The main intention is to make pickling and unpickling
+save, not to store secret information at client side.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseResponse.delete_cookie">
+<tt class="descname">delete_cookie</tt><big>(</big><em>key</em>, <em>**kwargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseResponse.delete_cookie"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseResponse.delete_cookie" title="Permalink to this definition">¶</a></dt>
+<dd><p>Delete a cookie. Be sure to use the same <cite>domain</cite> and <cite>path</cite>
+settings as used to create the cookie.</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="class">
+<dt id="bottle.LocalResponse">
+<em class="property">class </em><tt class="descname">LocalResponse</tt><big>(</big><em>body=''</em>, <em>status=None</em>, <em>**headers</em><big>)</big><a class="reference internal" href="_modules/bottle.html#LocalResponse"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.LocalResponse" title="Permalink to this definition">¶</a></dt>
+<dd><p>A thread-local subclass of <a class="reference internal" href="#bottle.BaseResponse" title="bottle.BaseResponse"><tt class="xref py py-class docutils literal"><span class="pre">BaseResponse</span></tt></a> with a different
+set of attribues for each thread. There is usually only one global
+instance of this class (<a class="reference internal" href="#bottle.response" title="bottle.response"><tt class="xref py py-data docutils literal"><span class="pre">response</span></tt></a>). Its attributes are used
+to build the HTTP response at the end of the request/response cycle.</p>
+<dl class="attribute">
+<dt id="bottle.LocalResponse.body">
+<tt class="descname">body</tt><a class="headerlink" href="#bottle.LocalResponse.body" title="Permalink to this definition">¶</a></dt>
+<dd><p>Thread-local property stored in <tt class="xref py py-data docutils literal"><span class="pre">_lctx.response_body</span></tt></p>
+</dd></dl>
+
+</dd></dl>
+
+<p>The following two classes can be raised as an exception. The most noticeable difference is that bottle invokes error handlers for <a class="reference internal" href="#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-class docutils literal"><span class="pre">HTTPError</span></tt></a>, but not for <a class="reference internal" href="#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-class docutils literal"><span class="pre">HTTPResponse</span></tt></a> or other response types.</p>
+<dl class="exception">
+<dt id="bottle.HTTPResponse">
+<em class="property">exception </em><tt class="descname">HTTPResponse</tt><big>(</big><em>body=''</em>, <em>status=None</em>, <em>header=None</em>, <em>**headers</em><big>)</big><a class="reference internal" href="_modules/bottle.html#HTTPResponse"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.HTTPResponse" title="Permalink to this definition">¶</a></dt>
+<dd><dl class="attribute">
+<dt id="bottle.HTTPResponse.output">
+<tt class="descname">output</tt><a class="headerlink" href="#bottle.HTTPResponse.output" title="Permalink to this definition">¶</a></dt>
+<dd><p>Alias for .body</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="exception">
+<dt id="bottle.HTTPError">
+<em class="property">exception </em><tt class="descname">HTTPError</tt><big>(</big><em>status=None</em>, <em>body=None</em>, <em>exception=None</em>, <em>traceback=None</em>, <em>header=None</em>, <em>**headers</em><big>)</big><a class="reference internal" href="_modules/bottle.html#HTTPError"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.HTTPError" title="Permalink to this definition">¶</a></dt>
+<dd></dd></dl>
+
+</div>
+<div class="section" id="templates">
+<h2>Templates<a class="headerlink" href="#templates" title="Permalink to this headline">¶</a></h2>
+<p>All template engines supported by <a class="reference internal" href="tutorial.html#module-bottle" title="bottle"><tt class="xref py py-mod docutils literal"><span class="pre">bottle</span></tt></a> implement the <a class="reference internal" href="#bottle.BaseTemplate" title="bottle.BaseTemplate"><tt class="xref py py-class docutils literal"><span class="pre">BaseTemplate</span></tt></a> API. This way it is possible to switch and mix template engines without changing the application code at all.</p>
+<dl class="class">
+<dt id="bottle.BaseTemplate">
+<em class="property">class </em><tt class="descname">BaseTemplate</tt><big>(</big><em>source=None</em>, <em>name=None</em>, <em>lookup=</em><span class="optional">[</span><span class="optional">]</span>, <em>encoding='utf8'</em>, <em>**settings</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseTemplate"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseTemplate" title="Permalink to this definition">¶</a></dt>
+<dd><p>Base class and minimal API for template adapters</p>
+<dl class="method">
+<dt id="bottle.BaseTemplate.__init__">
+<tt class="descname">__init__</tt><big>(</big><em>source=None</em>, <em>name=None</em>, <em>lookup=</em><span class="optional">[</span><span class="optional">]</span>, <em>encoding='utf8'</em>, <em>**settings</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseTemplate.__init__"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseTemplate.__init__" title="Permalink to this definition">¶</a></dt>
+<dd><p>Create a new template.
+If the source parameter (str or buffer) is missing, the name argument
+is used to guess a template filename. Subclasses can assume that
+self.source and/or self.filename are set. Both are strings.
+The lookup, encoding and settings parameters are stored as instance
+variables.
+The lookup parameter stores a list containing directory paths.
+The encoding parameter should be used to decode byte strings or files.
+The settings parameter contains a dict for engine-specific settings.</p>
+</dd></dl>
+
+<dl class="classmethod">
+<dt id="bottle.BaseTemplate.search">
+<em class="property">classmethod </em><tt class="descname">search</tt><big>(</big><em>name</em>, <em>lookup=</em><span class="optional">[</span><span class="optional">]</span><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseTemplate.search"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseTemplate.search" title="Permalink to this definition">¶</a></dt>
+<dd><p>Search name in all directories specified in lookup.
+First without, then with common extensions. Return first hit.</p>
+</dd></dl>
+
+<dl class="classmethod">
+<dt id="bottle.BaseTemplate.global_config">
+<em class="property">classmethod </em><tt class="descname">global_config</tt><big>(</big><em>key</em>, <em>*args</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseTemplate.global_config"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseTemplate.global_config" title="Permalink to this definition">¶</a></dt>
+<dd><p>This reads or sets the global settings stored in class.settings.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseTemplate.prepare">
+<tt class="descname">prepare</tt><big>(</big><em>**options</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseTemplate.prepare"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseTemplate.prepare" title="Permalink to this definition">¶</a></dt>
+<dd><p>Run preparations (parsing, caching, ...).
+It should be possible to call this again to refresh a template or to
+update settings.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.BaseTemplate.render">
+<tt class="descname">render</tt><big>(</big><em>*args</em>, <em>**kwargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#BaseTemplate.render"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.BaseTemplate.render" title="Permalink to this definition">¶</a></dt>
+<dd><p>Render the template with the specified local variables and return
+a single byte or unicode string. If it is a byte string, the encoding
+must match self.encoding. This method must be thread-safe!
+Local variables may be provided in dictionaries (<a href="#id1"><span class="problematic" id="id2">*</span></a>args)
+or directly, as keywords (<a href="#id3"><span class="problematic" id="id4">**</span></a>kwargs).</p>
+</dd></dl>
+
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.view">
+<tt class="descname">view</tt><big>(</big><em>tpl_name</em>, <em>**defaults</em><big>)</big><a class="reference internal" href="_modules/bottle.html#view"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.view" title="Permalink to this definition">¶</a></dt>
+<dd><p>Decorator: renders a template for a handler.
+The handler can control its behavior like that:</p>
+<ul class="simple">
+<li>return a dict of template vars to fill out the template</li>
+<li>return something other than a dict and the view decorator will not
+process the template, but return the handler result as is.
+This includes returning a HTTPResponse(dict) to get,
+for instance, JSON with autojson or other castfilters.</li>
+</ul>
+</dd></dl>
+
+<dl class="function">
+<dt id="bottle.template">
+<tt class="descname">template</tt><big>(</big><em>*args</em>, <em>**kwargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#template"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.template" title="Permalink to this definition">¶</a></dt>
+<dd><p>Get a rendered template as a string iterator.
+You can use a name, a filename or a template string as first parameter.
+Template rendering arguments can be passed as dictionaries
+or directly (as keyword arguments).</p>
+</dd></dl>
+
+<p>You can write your own adapter for your favourite template engine or use one of the predefined adapters. Currently there are four fully supported template engines:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="24%" />
+<col width="31%" />
+<col width="20%" />
+<col width="24%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Class</th>
+<th class="head">URL</th>
+<th class="head">Decorator</th>
+<th class="head">Render function</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td><a class="reference internal" href="stpl.html#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a></td>
+<td><a class="reference internal" href="stpl.html"><em>SimpleTemplate Engine</em></a></td>
+<td><a class="reference internal" href="#bottle.view" title="bottle.view"><tt class="xref py py-func docutils literal"><span class="pre">view()</span></tt></a></td>
+<td><a class="reference internal" href="#bottle.template" title="bottle.template"><tt class="xref py py-func docutils literal"><span class="pre">template()</span></tt></a></td>
+</tr>
+<tr class="row-odd"><td><tt class="xref py py-class docutils literal"><span class="pre">MakoTemplate</span></tt></td>
+<td><a class="reference external" href="http://www.makotemplates.org">http://www.makotemplates.org</a></td>
+<td><tt class="xref py py-func docutils literal"><span class="pre">mako_view()</span></tt></td>
+<td><tt class="xref py py-func docutils literal"><span class="pre">mako_template()</span></tt></td>
+</tr>
+<tr class="row-even"><td><tt class="xref py py-class docutils literal"><span class="pre">CheetahTemplate</span></tt></td>
+<td><a class="reference external" href="http://www.cheetahtemplate.org/">http://www.cheetahtemplate.org/</a></td>
+<td><tt class="xref py py-func docutils literal"><span class="pre">cheetah_view()</span></tt></td>
+<td><tt class="xref py py-func docutils literal"><span class="pre">cheetah_template()</span></tt></td>
+</tr>
+<tr class="row-odd"><td><tt class="xref py py-class docutils literal"><span class="pre">Jinja2Template</span></tt></td>
+<td><a class="reference external" href="http://jinja.pocoo.org/">http://jinja.pocoo.org/</a></td>
+<td><tt class="xref py py-func docutils literal"><span class="pre">jinja2_view()</span></tt></td>
+<td><tt class="xref py py-func docutils literal"><span class="pre">jinja2_template()</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>To use <tt class="xref py py-class docutils literal"><span class="pre">MakoTemplate</span></tt> as your default template engine, just import its specialised decorator and render function:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">mako_view</span> <span class="k">as</span> <span class="n">view</span><span class="p">,</span> <span class="n">mako_template</span> <span class="k">as</span> <span class="n">template</span>
+</pre></div>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">API Reference</a><ul>
+<li><a class="reference internal" href="#module-contents">Module Contents</a><ul>
+<li><a class="reference internal" href="#routing">Routing</a></li>
+<li><a class="reference internal" href="#wsgi-and-http-utilities">WSGI and HTTP Utilities</a></li>
+<li><a class="reference internal" href="#data-structures">Data Structures</a></li>
+<li><a class="reference internal" href="#exceptions">Exceptions</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#the-bottle-class">The <tt class="docutils literal"><span class="pre">Bottle</span></tt> Class</a></li>
+<li><a class="reference internal" href="#the-request-object">The <tt class="docutils literal"><span class="pre">Request</span></tt> Object</a></li>
+<li><a class="reference internal" href="#the-response-object">The <tt class="docutils literal"><span class="pre">Response</span></tt> Object</a></li>
+<li><a class="reference internal" href="#templates">Templates</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="stpl.html"
+                        title="previous chapter">SimpleTemplate Engine</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="plugins/index.html"
+                        title="next chapter">List of available Plugins</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/api.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="plugins/index.html" title="List of available Plugins"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="stpl.html" title="SimpleTemplate Engine"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_api';
+      var disqus_title = 'API Reference';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/async.html b/html/async.html
new file mode 100644 (file)
index 0000000..0e39b74
--- /dev/null
@@ -0,0 +1,301 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Primer to Asynchronous Applications &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Recipes" href="recipes.html" />
+    <link rel="prev" title="Tutorial: Todo-List Application" href="tutorial_app.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="recipes.html" title="Recipes"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="tutorial_app.html" title="Tutorial: Todo-List Application"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="primer-to-asynchronous-applications">
+<h1>Primer to Asynchronous Applications<a class="headerlink" href="#primer-to-asynchronous-applications" title="Permalink to this headline">¶</a></h1>
+<p>Asynchronous design patterns don&#8217;t mix well with the synchronous nature of <a class="reference external" href="http://www.python.org/dev/peps/pep-3333/">WSGI</a>. This is why most asynchronous frameworks (tornado, twisted, ...) implement a specialized API to expose their asynchronous features. Bottle is a WSGI framework and shares the synchronous nature of WSGI, but thanks to the awesome <a class="reference external" href="http://www.gevent.org/">gevent project</a>, it is still possible to write asynchronous applications with bottle. This article documents the usage of Bottle with Asynchronous WSGI.</p>
+<div class="section" id="the-limits-of-synchronous-wsgi">
+<h2>The Limits of Synchronous WSGI<a class="headerlink" href="#the-limits-of-synchronous-wsgi" title="Permalink to this headline">¶</a></h2>
+<p>Briefly worded, the <a class="reference external" href="http://www.python.org/dev/peps/pep-3333/">WSGI specification (pep 3333)</a> defines a request/response circle as follows: The application callable is invoked once for each request and must return a body iterator. The server then iterates over the body and writes each chunk to the socket. As soon as the body iterator is exhausted, the client connection is closed.</p>
+<p>Simple enough, but there is a snag: All this happens synchronously. If your application needs to wait for data (IO, sockets, databases, ...), it must either yield empty strings (busy wait) or block the current thread. Both solutions occupy the handling thread and prevent it from answering new requests. There is consequently only one ongoing request per thread.</p>
+<p>Most servers limit the number of threads to avoid their relatively high overhead. Pools of 20 or less threads are common. As soon as all threads are occupied, any new connection is stalled. The server is effectively dead for everyone else. If you want to implement a chat that uses long-polling ajax requests to get real-time updates, you&#8217;d reach the limited at 20 concurrent connections. That&#8217;s a pretty small chat.</p>
+</div>
+<div class="section" id="greenlets-to-the-rescue">
+<h2>Greenlets to the rescue<a class="headerlink" href="#greenlets-to-the-rescue" title="Permalink to this headline">¶</a></h2>
+<p>Most servers limit the size of their worker pools to a relatively low number of concurrent threads, due to the high overhead involved in switching between and creating new threads. While threads are cheap compared to processes (forks), they are still expensive to create for each new connection.</p>
+<p>The <a class="reference external" href="http://www.gevent.org/">gevent</a> module adds <em>greenlets</em> to the mix. Greenlets behave similar to traditional threads, but are very cheap to create. A gevent-based server can spawn thousands of greenlets (one for each connection) with almost no overhead. Blocking individual greenlets has no impact on the servers ability to accept new requests. The number of concurrent connections is virtually unlimited.</p>
+<p>This makes creating asynchronous applications incredibly easy, because they look and feel like synchronous applications. A gevent-based server is actually not asynchronous, but massively multi-threaded. Here is an example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">gevent</span> <span class="kn">import</span> <span class="n">monkey</span><span class="p">;</span> <span class="n">monkey</span><span class="o">.</span><span class="n">patch_all</span><span class="p">()</span>
+
+<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span>
+<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/stream&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">stream</span><span class="p">():</span>
+    <span class="k">yield</span> <span class="s">&#39;START&#39;</span>
+    <span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
+    <span class="k">yield</span> <span class="s">&#39;MIDDLE&#39;</span>
+    <span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
+    <span class="k">yield</span> <span class="s">&#39;END&#39;</span>
+
+<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;0.0.0.0&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span> <span class="n">server</span><span class="o">=</span><span class="s">&#39;gevent&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>The first line is important. It causes gevent to monkey-patch most of Python&#8217;s blocking APIs to not block the current thread, but pass the CPU to the next greenlet instead. It actually replaces Python&#8217;s threading with gevent-based pseudo-threads. This is why you can still use <tt class="docutils literal"><span class="pre">time.sleep()</span></tt> which would normally block the whole thread. If you don&#8217;t feel comfortable with monkey-patching python built-ins, you can use the corresponding gevent functions (<tt class="docutils literal"><span class="pre">gevent.sleep()</span></tt> in this case).</p>
+<p>If you run this script and point your browser to <tt class="docutils literal"><span class="pre">http://localhost:8080/stream</span></tt>, you should see <cite>START</cite>, <cite>MIDDLE</cite>, and <cite>END</cite> show up one by one (rather than waiting 8 seconds to see them all at once). It works exactly as with normal threads, but now your server can handle thousands of concurrent requests without any problems.</p>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">Some browsers buffer a certain amount of data before they start rendering a
+page. You might need to yield more than a few bytes to see an effect in
+these browsers. Additionally, many browsers have a limit of one concurrent
+connection per URL. If this is the case, you can use a second browser or a
+benchmark tool (e.g. <cite>ab</cite> or <cite>httperf</cite>) to measure performance.</p>
+</div>
+</div>
+<div class="section" id="event-callbacks">
+<h2>Event Callbacks<a class="headerlink" href="#event-callbacks" title="Permalink to this headline">¶</a></h2>
+<p>A very common design pattern in asynchronous frameworks (including tornado, twisted, node.js and friends) is to use non-blocking APIs and bind callbacks to asynchronous events. The socket object is kept open until it is closed explicitly to allow callbacks to write to the socket at a later point. Here is an example based on the <a class="reference external" href="http://www.tornadoweb.org/documentation#non-blocking-asynchronous-requests">tornado library</a>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">MainHandler</span><span class="p">(</span><span class="n">tornado</span><span class="o">.</span><span class="n">web</span><span class="o">.</span><span class="n">RequestHandler</span><span class="p">):</span>
+    <span class="nd">@tornado.web.asynchronous</span>
+    <span class="k">def</span> <span class="nf">get</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+        <span class="n">worker</span> <span class="o">=</span> <span class="n">SomeAsyncWorker</span><span class="p">()</span>
+        <span class="n">worker</span><span class="o">.</span><span class="n">on_data</span><span class="p">(</span><span class="k">lambda</span> <span class="n">chunk</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">chunk</span><span class="p">))</span>
+        <span class="n">worker</span><span class="o">.</span><span class="n">on_finish</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">finish</span><span class="p">())</span>
+</pre></div>
+</div>
+<p>The main benefit is that the request handler terminates early. The handling thread can move on and accept new requests while the callbacks continue to write to sockets of previous requests. This is how these frameworks manage to process a lot of concurrent requests with only a small number of OS threads.</p>
+<p>With Gevent+WSGI, things are different: First, terminating early has no benefit because we have an unlimited pool of (pseudo)threads to accept new connections. Second, we cannot terminate early because that would close the socket (as required by WSGI). Third, we must return an iterable to conform to WSGI.</p>
+<p>In order to conform to the WSGI standard, all we have to do is to return a body iterable that we can write to asynchronously. With the help of <a class="reference external" href="http://www.gevent.org/gevent.queue.html">gevent.queue</a>, we can <em>simulate</em> a detached socket and rewrite the previous example as follows:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/fetch&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">fetch</span><span class="p">():</span>
+    <span class="n">body</span> <span class="o">=</span> <span class="n">gevent</span><span class="o">.</span><span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>
+    <span class="n">worker</span> <span class="o">=</span> <span class="n">SomeAsyncWorker</span><span class="p">()</span>
+    <span class="n">worker</span><span class="o">.</span><span class="n">on_data</span><span class="p">(</span><span class="k">lambda</span> <span class="n">chunk</span><span class="p">:</span> <span class="n">body</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">chunk</span><span class="p">))</span>
+    <span class="n">worker</span><span class="o">.</span><span class="n">on_finish</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">body</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="ne">StopIteration</span><span class="p">))</span>
+    <span class="k">return</span> <span class="n">body</span>
+</pre></div>
+</div>
+<p>From the server perspective, the queue object is iterable. It blocks if empty and stops as soon as it reaches <tt class="docutils literal"><span class="pre">StopIteration</span></tt>. This conforms to WSGI. On the application side, the queue object behaves like a non-blocking socket. You can write to it at any time, pass it around and even start a new (pseudo)thread that writes to it asynchronously. This is how long-polling is implemented most of the time.</p>
+</div>
+<div class="section" id="finally-websockets">
+<h2>Finally: WebSockets<a class="headerlink" href="#finally-websockets" title="Permalink to this headline">¶</a></h2>
+<p>Lets forget about the low-level details for a while and speak about WebSockets. Since you are reading this article, you probably know what WebSockets are: A bidirectional communication channel between a browser (client) and a web application (server).</p>
+<p>Thankfully the <a class="reference external" href="http://pypi.python.org/pypi/gevent-websocket/">gevent-websocket</a> package does all the hard work for us. Here is a simple WebSocket endpoint that receives messages and just sends them back to the client:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">request</span><span class="p">,</span> <span class="n">Bottle</span><span class="p">,</span> <span class="n">abort</span>
+<span class="n">app</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/websocket&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">handle_websocket</span><span class="p">():</span>
+    <span class="n">wsock</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;wsgi.websocket&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">wsock</span><span class="p">:</span>
+        <span class="n">abort</span><span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="s">&#39;Expected WebSocket request.&#39;</span><span class="p">)</span>
+
+    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
+        <span class="k">try</span><span class="p">:</span>
+            <span class="n">message</span> <span class="o">=</span> <span class="n">wsock</span><span class="o">.</span><span class="n">receive</span><span class="p">()</span>
+            <span class="n">wsock</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s">&quot;Your message was: </span><span class="si">%r</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">message</span><span class="p">)</span>
+        <span class="k">except</span> <span class="n">WebSocketError</span><span class="p">:</span>
+            <span class="k">break</span>
+
+<span class="kn">from</span> <span class="nn">gevent.pywsgi</span> <span class="kn">import</span> <span class="n">WSGIServer</span>
+<span class="kn">from</span> <span class="nn">geventwebsocket</span> <span class="kn">import</span> <span class="n">WebSocketHandler</span><span class="p">,</span> <span class="n">WebSocketError</span>
+<span class="n">server</span> <span class="o">=</span> <span class="n">WSGIServer</span><span class="p">((</span><span class="s">&quot;0.0.0.0&quot;</span><span class="p">,</span> <span class="mi">8080</span><span class="p">),</span> <span class="n">app</span><span class="p">,</span>
+                    <span class="n">handler_class</span><span class="o">=</span><span class="n">WebSocketHandler</span><span class="p">)</span>
+<span class="n">server</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>The while-loop runs until the client closes the connection. You get the idea :)</p>
+<p>The client-site JavaScript API is really straight forward, too:</p>
+<div class="highlight-python"><pre>&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+  &lt;script type="text/javascript"&gt;
+    var ws = new WebSocket("ws://example.com:8080/websocket");
+    ws.onopen = function() {
+        ws.send("Hello, world");
+    };
+    ws.onmessage = function (evt) {
+        alert(evt.data);
+    };
+  &lt;/script&gt;
+&lt;/head&gt;
+&lt;/html&gt;</pre>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Primer to Asynchronous Applications</a><ul>
+<li><a class="reference internal" href="#the-limits-of-synchronous-wsgi">The Limits of Synchronous WSGI</a></li>
+<li><a class="reference internal" href="#greenlets-to-the-rescue">Greenlets to the rescue</a></li>
+<li><a class="reference internal" href="#event-callbacks">Event Callbacks</a></li>
+<li><a class="reference internal" href="#finally-websockets">Finally: WebSockets</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="tutorial_app.html"
+                        title="previous chapter">Tutorial: Todo-List Application</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="recipes.html"
+                        title="next chapter">Recipes</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/async.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="recipes.html" title="Recipes"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="tutorial_app.html" title="Tutorial: Todo-List Application"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_async';
+      var disqus_title = 'Primer to Asynchronous Applications';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/changelog.html b/html/changelog.html
new file mode 100644 (file)
index 0000000..8b8aeef
--- /dev/null
@@ -0,0 +1,380 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Release Notes and Changelog &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Developer Notes" href="development.html" />
+    <link rel="prev" title="Frequently Asked Questions" href="faq.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="development.html" title="Developer Notes"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="faq.html" title="Frequently Asked Questions"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="release-notes-and-changelog">
+<h1>Release Notes and Changelog<a class="headerlink" href="#release-notes-and-changelog" title="Permalink to this headline">¶</a></h1>
+<div class="section" id="release-0-11">
+<h2>Release 0.11<a class="headerlink" href="#release-0-11" title="Permalink to this headline">¶</a></h2>
+<ul class="simple">
+<li>Native support for Python 2.x and 3.x syntax. No need to run 2to3 anymore.</li>
+<li>Support for partial downloads (<tt class="docutils literal"><span class="pre">Range</span></tt> header) in <tt class="xref py py-func docutils literal"><span class="pre">static_file()</span></tt>.</li>
+<li>The new <a class="reference internal" href="api.html#bottle.ResourceManager" title="bottle.ResourceManager"><tt class="xref py py-class docutils literal"><span class="pre">ResourceManager</span></tt></a> interface helps locating files bundled with an application.</li>
+<li>Added a server adapter for <a class="reference external" href="http://docs.pylonsproject.org/projects/waitress/en/latest/">waitress</a>.</li>
+<li>New <a class="reference internal" href="api.html#bottle.Bottle.merge" title="bottle.Bottle.merge"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.merge()</span></tt></a> method to install all routes from one application into another.</li>
+<li>New <a class="reference internal" href="api.html#bottle.BaseRequest.app" title="bottle.BaseRequest.app"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.app</span></tt></a> property to get the application object that handles a request.</li>
+<li>Added <a class="reference internal" href="api.html#bottle.FormsDict.decode" title="bottle.FormsDict.decode"><tt class="xref py py-meth docutils literal"><span class="pre">FormsDict.decode()</span></tt></a> to get an all-unicode version (needed by WTForms).</li>
+<li><a class="reference internal" href="api.html#bottle.MultiDict" title="bottle.MultiDict"><tt class="xref py py-class docutils literal"><span class="pre">MultiDict</span></tt></a> and subclasses are now pickle-able.</li>
+</ul>
+<p class="rubric">API Changes</p>
+<ul class="simple">
+<li><tt class="xref py py-attr docutils literal"><span class="pre">Response.status</span></tt> is a read-write property that can be assigned either a numeric status code or a status string with a reason phrase (<tt class="docutils literal"><span class="pre">200</span> <span class="pre">OK</span></tt>). The return value is now a string to better match existing APIs (WebOb, werkzeug). To be absolutely clear, you can use the read-only properties <a class="reference internal" href="api.html#bottle.BaseResponse.status_code" title="bottle.BaseResponse.status_code"><tt class="xref py py-attr docutils literal"><span class="pre">BaseResponse.status_code</span></tt></a> and <a class="reference internal" href="api.html#bottle.BaseResponse.status_line" title="bottle.BaseResponse.status_line"><tt class="xref py py-attr docutils literal"><span class="pre">BaseResponse.status_line</span></tt></a>.</li>
+</ul>
+<p class="rubric">API Deprecations</p>
+<ul class="simple">
+<li><tt class="xref py py-class docutils literal"><span class="pre">SimpleTALTemplate</span></tt> is now deprecating. There seems to be no demand.</li>
+</ul>
+</div>
+<div class="section" id="release-0-10">
+<h2>Release 0.10<a class="headerlink" href="#release-0-10" title="Permalink to this headline">¶</a></h2>
+<ul class="simple">
+<li>Plugin API v2<ul>
+<li>To use the new API, set <a class="reference internal" href="plugindev.html#bottle.Plugin.api" title="bottle.Plugin.api"><tt class="xref py py-attr docutils literal"><span class="pre">Plugin.api</span></tt></a> to <tt class="docutils literal"><span class="pre">2</span></tt>.</li>
+<li><a class="reference internal" href="plugindev.html#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.apply()</span></tt></a> receives a <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> object instead of a context dictionary as second parameter. The new object offers some additional information and may be extended in the future.</li>
+<li>Plugin names are considered unique now. The topmost plugin with a given name on a given route is installed, all other plugins with the same name are silently ignored.</li>
+</ul>
+</li>
+<li>The Request/Response Objects<ul>
+<li>Added <a class="reference internal" href="api.html#bottle.BaseRequest.json" title="bottle.BaseRequest.json"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.json</span></tt></a>, <a class="reference internal" href="api.html#bottle.BaseRequest.remote_route" title="bottle.BaseRequest.remote_route"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.remote_route</span></tt></a>, <a class="reference internal" href="api.html#bottle.BaseRequest.remote_addr" title="bottle.BaseRequest.remote_addr"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.remote_addr</span></tt></a>, <a class="reference internal" href="api.html#bottle.BaseRequest.query" title="bottle.BaseRequest.query"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.query</span></tt></a> and <a class="reference internal" href="api.html#bottle.BaseRequest.script_name" title="bottle.BaseRequest.script_name"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.script_name</span></tt></a>.</li>
+<li>Added <a class="reference internal" href="api.html#bottle.BaseResponse.status_line" title="bottle.BaseResponse.status_line"><tt class="xref py py-attr docutils literal"><span class="pre">BaseResponse.status_line</span></tt></a> and <a class="reference internal" href="api.html#bottle.BaseResponse.status_code" title="bottle.BaseResponse.status_code"><tt class="xref py py-attr docutils literal"><span class="pre">BaseResponse.status_code</span></tt></a> attributes. In future releases, <a class="reference internal" href="api.html#bottle.BaseResponse.status" title="bottle.BaseResponse.status"><tt class="xref py py-attr docutils literal"><span class="pre">BaseResponse.status</span></tt></a> will return a string (e.g. <tt class="docutils literal"><span class="pre">200</span> <span class="pre">OK</span></tt>) instead of an integer to match the API of other common frameworks. To make the transition as smooth as possible, you should use the verbose attributes from now on.</li>
+<li>Replaced <a class="reference internal" href="api.html#bottle.MultiDict" title="bottle.MultiDict"><tt class="xref py py-class docutils literal"><span class="pre">MultiDict</span></tt></a> with a specialized <a class="reference internal" href="api.html#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a> in many places. The new dict implementation allows attribute access and handles unicode form values transparently.</li>
+</ul>
+</li>
+<li>Templates<ul>
+<li>Added three new functions to the SimpleTemplate default namespace that handle undefined variables: <a class="reference internal" href="stpl.html#stpl.defined" title="stpl.defined"><tt class="xref py py-func docutils literal"><span class="pre">stpl.defined()</span></tt></a>, <a class="reference internal" href="stpl.html#stpl.get" title="stpl.get"><tt class="xref py py-func docutils literal"><span class="pre">stpl.get()</span></tt></a> and <a class="reference internal" href="stpl.html#stpl.setdefault" title="stpl.setdefault"><tt class="xref py py-func docutils literal"><span class="pre">stpl.setdefault()</span></tt></a>.</li>
+<li>The default escape function for SimpleTemplate now additionally escapes single and double quotes.</li>
+</ul>
+</li>
+<li>Routing<ul>
+<li>A new route syntax (e.g. <tt class="docutils literal"><span class="pre">/object/&lt;id:int&gt;</span></tt>) and support for route wildcard filters.</li>
+<li>Four new wildcard filters: <cite>int</cite>, <cite>float</cite>, <cite>path</cite> and <cite>re</cite>.</li>
+</ul>
+</li>
+<li>Oher changes<ul>
+<li>Added command line interface to load applications and start servers.</li>
+<li>Introduced a <tt class="xref py py-class docutils literal"><span class="pre">ConfigDict</span></tt> that makes accessing configuration a lot easier (attribute access and auto-expanding namespaces).</li>
+<li>Added support for raw WSGI applications to <a class="reference internal" href="api.html#bottle.Bottle.mount" title="bottle.Bottle.mount"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.mount()</span></tt></a>.</li>
+<li><a class="reference internal" href="api.html#bottle.Bottle.mount" title="bottle.Bottle.mount"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.mount()</span></tt></a> parameter order changed.</li>
+<li><a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a> now accpets an import string for the <tt class="docutils literal"><span class="pre">callback</span></tt> parameter.</li>
+<li>Dropped Gunicorn 0.8 support. Current supported version is 0.13.</li>
+<li>Added custom options to Gunicorn server.</li>
+<li>Finally dropped support for type filters. Replace with a custom plugin of needed.</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="release-0-9">
+<h2>Release 0.9<a class="headerlink" href="#release-0-9" title="Permalink to this headline">¶</a></h2>
+<p class="rubric">Whats new?</p>
+<ul class="simple">
+<li>A brand new plugin-API. See <a class="reference internal" href="tutorial.html#plugins"><em>Plugins</em></a> and <a class="reference internal" href="plugindev.html"><em>Plugin Development Guide</em></a> for details.</li>
+<li>The <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator got a lot of new features. See <a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a> for details.</li>
+<li>New server adapters for <a class="reference external" href="http://www.gevent.org/">gevent</a>, <a class="reference external" href="http://meinheld.org/">meinheld</a> and <a class="reference external" href="https://github.com/jonashaag/bjoern">bjoern</a>.</li>
+<li>Support for SimpleTAL templates.</li>
+<li>Better runtime exception handling for mako templates in debug mode.</li>
+<li>Lots of documentation, fixes and small improvements.</li>
+<li>A new <tt class="xref py py-data docutils literal"><span class="pre">Request.urlparts</span></tt> property.</li>
+</ul>
+<p class="rubric">Performance improvements</p>
+<ul class="simple">
+<li>The <tt class="xref py py-class docutils literal"><span class="pre">Router</span></tt> now special-cases <tt class="docutils literal"><span class="pre">wsgi.run_once</span></tt> environments to speed up CGI.</li>
+<li>Reduced module load time by ~30% and optimized template parser. See <a class="reference external" href="/commit/8ccb2d">8ccb2d</a>, <a class="reference external" href="/commit/f72a7c">f72a7c</a> and <a class="reference external" href="/commit/b14b9a">b14b9a</a> for details.</li>
+<li>Support for &#8220;App Caching&#8221; on Google App Engine. See <a class="reference external" href="/commit/af93ec">af93ec</a>.</li>
+<li>Some of the rarely used or deprecated features are now plugins that avoid overhead if the feature is not used.</li>
+</ul>
+<p class="rubric">API changes</p>
+<p>This release is mostly backward compatible, but some APIs are marked deprecated now and will be removed for the next release. Most noteworthy:</p>
+<ul class="simple">
+<li>The <tt class="docutils literal"><span class="pre">static</span></tt> route parameter is deprecated. You can escape wild-cards with a backslash.</li>
+<li>Type-based output filters are deprecated. They can easily be replaced with plugins.</li>
+</ul>
+</div>
+<div class="section" id="release-0-8">
+<h2>Release 0.8<a class="headerlink" href="#release-0-8" title="Permalink to this headline">¶</a></h2>
+<p class="rubric">API changes</p>
+<p>These changes may break compatibility with previous versions.</p>
+<ul class="simple">
+<li>The built-in Key/Value database is not available anymore. It is marked deprecated since 0.6.4</li>
+<li>The Route syntax and behaviour changed.<ul>
+<li>Regular expressions must be encapsulated with <tt class="docutils literal"><span class="pre">#</span></tt>. In 0.6 all non-alphanumeric characters not present in the regular expression were allowed.</li>
+<li>Regular expressions not part of a route wildcard are escaped automatically. You don&#8217;t have to escape dots or other regular control characters anymore. In 0.6 the whole URL was interpreted as a regular expression. You can use anonymous wildcards (<tt class="docutils literal"><span class="pre">/index:#(\.html)?#</span></tt>) to achieve a similar behaviour.</li>
+</ul>
+</li>
+<li>The <tt class="docutils literal"><span class="pre">BreakTheBottle</span></tt> exception is gone. Use <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-class docutils literal"><span class="pre">HTTPResponse</span></tt></a> instead.</li>
+<li>The <a class="reference internal" href="stpl.html#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> engine escapes HTML special characters in <tt class="docutils literal"><span class="pre">{{bad_html}}</span></tt> expressions automatically. Use the new <tt class="docutils literal"><span class="pre">{{!good_html}}</span></tt> syntax to get old behaviour (no escaping).</li>
+<li>The <a class="reference internal" href="stpl.html#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> engine returns unicode strings instead of lists of byte strings.</li>
+<li><tt class="docutils literal"><span class="pre">bottle.optimize()</span></tt> and the automatic route optimization is obsolete.</li>
+<li>Some functions and attributes were renamed:<ul>
+<li><tt class="xref py py-attr docutils literal"><span class="pre">Request._environ</span></tt> is now <tt class="xref py py-attr docutils literal"><span class="pre">Request.environ</span></tt></li>
+<li><tt class="xref py py-attr docutils literal"><span class="pre">Response.header</span></tt> is now <tt class="xref py py-attr docutils literal"><span class="pre">Response.headers</span></tt></li>
+<li><a class="reference internal" href="api.html#bottle.default_app" title="bottle.default_app"><tt class="xref py py-func docutils literal"><span class="pre">default_app()</span></tt></a> is obsolete. Use <a class="reference internal" href="api.html#bottle.app" title="bottle.app"><tt class="xref py py-func docutils literal"><span class="pre">app()</span></tt></a> instead.</li>
+</ul>
+</li>
+<li>The default <tt class="xref py py-func docutils literal"><span class="pre">redirect()</span></tt> code changed from 307 to 303.</li>
+<li>Removed support for <tt class="docutils literal"><span class="pre">&#64;default</span></tt>. Use <tt class="docutils literal"><span class="pre">&#64;error(404)</span></tt> instead.</li>
+</ul>
+<p class="rubric">New features</p>
+<p>This is an incomplete list of new features and improved functionality.</p>
+<ul class="simple">
+<li>The <a class="reference internal" href="api.html#bottle.Request" title="bottle.Request"><tt class="xref py py-class docutils literal"><span class="pre">Request</span></tt></a> object got new properties: <tt class="xref py py-attr docutils literal"><span class="pre">Request.body</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">Request.auth</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">Request.url</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">Request.header</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">Request.forms</span></tt>, <tt class="xref py py-attr docutils literal"><span class="pre">Request.files</span></tt>.</li>
+<li>The <tt class="xref py py-meth docutils literal"><span class="pre">Response.set_cookie()</span></tt> and <tt class="xref py py-meth docutils literal"><span class="pre">Request.get_cookie()</span></tt> methods are now able to encode and decode python objects. This is called a <em>secure cookie</em> because the encoded values are signed and protected from changes on client side. All pickle-able data structures are allowed.</li>
+<li>The new <tt class="xref py py-class docutils literal"><span class="pre">Router</span></tt> class drastically improves performance for setups with lots of dynamic routes and supports named routes (named route + dict = URL string).</li>
+<li>It is now possible (and recommended) to return <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> and <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> instances or other exception objects instead of raising them.</li>
+<li>The new function <tt class="xref py py-func docutils literal"><span class="pre">static_file()</span></tt> equals <tt class="xref py py-func docutils literal"><span class="pre">send_file()</span></tt> but returns a <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> or <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> instead of raising it. <tt class="xref py py-func docutils literal"><span class="pre">send_file()</span></tt> is deprecated.</li>
+<li>New <a class="reference internal" href="api.html#bottle.get" title="bottle.get"><tt class="xref py py-func docutils literal"><span class="pre">get()</span></tt></a>, <a class="reference internal" href="api.html#bottle.post" title="bottle.post"><tt class="xref py py-func docutils literal"><span class="pre">post()</span></tt></a>, <a class="reference internal" href="api.html#bottle.put" title="bottle.put"><tt class="xref py py-func docutils literal"><span class="pre">put()</span></tt></a> and <a class="reference internal" href="api.html#bottle.delete" title="bottle.delete"><tt class="xref py py-func docutils literal"><span class="pre">delete()</span></tt></a> decorators.</li>
+<li>The <a class="reference internal" href="stpl.html#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> engine got full unicode support.</li>
+<li>Lots of non-critical bugfixes.</li>
+</ul>
+</div>
+</div>
+<div class="section" id="contributors">
+<h1>Contributors<a class="headerlink" href="#contributors" title="Permalink to this headline">¶</a></h1>
+<p>Bottle is written and maintained by Marcel Hellkamp &lt;<a class="reference external" href="mailto:marc&#37;&#52;&#48;bottlepy&#46;org">marc<span>&#64;</span>bottlepy<span>&#46;</span>org</a>&gt;.</p>
+<p>Thanks to all the people who found bugs, sent patches, spread the word, helped each other on the mailing-list and made this project possible. I hope the following (alphabetically sorted) list is complete. If you miss your name on that list (or want your name removed) please <a class="reference internal" href="contact.html"><em>tell me</em></a> or add it yourself.</p>
+<ul class="simple">
+<li>acasajus</li>
+<li>Adam R. Smith</li>
+<li>Alexey Borzenkov</li>
+<li>Alexis Daboville</li>
+<li>Anton I. Sipos</li>
+<li>Anton Kolechkin</li>
+<li>apexi200sx</li>
+<li>apheage</li>
+<li>BillMa</li>
+<li>Brad Greenlee</li>
+<li>Brandon Gilmore</li>
+<li>Branko Vukelic</li>
+<li>Brian Sierakowski</li>
+<li>Brian Wickman</li>
+<li>Carl Scharenberg</li>
+<li>Damien Degois</li>
+<li>David Buxton</li>
+<li>Duane Johnson</li>
+<li>fcamel</li>
+<li>Frank Murphy</li>
+<li>Frederic Junod</li>
+<li>goldfaber3012</li>
+<li>Greg Milby</li>
+<li>gstein</li>
+<li>Ian Davis</li>
+<li>Itamar Nabriski</li>
+<li>Iuri de Silvio</li>
+<li>Jaimie Murdock</li>
+<li>Jeff Nichols</li>
+<li>Jeremy Kelley</li>
+<li>joegester</li>
+<li>Johannes Krampf</li>
+<li>Jonas Haag</li>
+<li>Joshua Roesslein</li>
+<li>Karl</li>
+<li>Kraken</li>
+<li>Kyle Fritz</li>
+<li>m35</li>
+<li>Marcos Neves</li>
+<li>masklinn</li>
+<li>Michael Labbe</li>
+<li>Michael Soulier</li>
+<li><a class="reference external" href="http://reddit.com/r/python">reddit</a></li>
+<li>Robert Rollins</li>
+<li>rogererens</li>
+<li>rwxrwx</li>
+<li>Santiago Gala</li>
+<li>Sean M. Collins</li>
+<li>Sebastian Wollrath</li>
+<li>Seth</li>
+<li>Sigurd Høgsbro</li>
+<li>Stuart Rackham</li>
+<li>Sun Ning</li>
+<li>Tomás A. Schertel</li>
+<li>Tristan Zajonc</li>
+<li>voltron</li>
+<li>Wieland Hoffmann</li>
+<li>zombat</li>
+</ul>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Release Notes and Changelog</a><ul>
+<li><a class="reference internal" href="#release-0-11">Release 0.11</a></li>
+<li><a class="reference internal" href="#release-0-10">Release 0.10</a></li>
+<li><a class="reference internal" href="#release-0-9">Release 0.9</a></li>
+<li><a class="reference internal" href="#release-0-8">Release 0.8</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#contributors">Contributors</a></li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="faq.html"
+                        title="previous chapter">Frequently Asked Questions</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="development.html"
+                        title="next chapter">Developer Notes</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/changelog.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="development.html" title="Developer Notes"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="faq.html" title="Frequently Asked Questions"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_changelog';
+      var disqus_title = 'Release Notes and Changelog';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/contact.html b/html/contact.html
new file mode 100644 (file)
index 0000000..a49f880
--- /dev/null
@@ -0,0 +1,181 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Contact &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="contact">
+<h1>Contact<a class="headerlink" href="#contact" title="Permalink to this headline">¶</a></h1>
+<p class="rubric">About the Autor</p>
+<img alt="Photo" class="floatright" src="_images/myface_small.png" />
+<p>Hi, I&#8217;m <em>Marcel Hellkamp</em> (aka <em>defnull</em>), author of Bottle and the guy behind this website. I&#8217;m 27 years old and studying computer science at the Georg-August-University in Göttingen, Germany. Python is my favorite language, but I also code in ruby and JavaScript a lot. Watch me on <a class="reference external" href="http://twitter.com/bottlepy">twitter</a> or visit my profile at <a class="reference external" href="http://github.com/defnull">GitHub</a> to get in contact. A <a class="reference external" href="http://groups.google.de/group/bottlepy">mailinglist</a> is open for Bottle related questions, too.</p>
+<p class="rubric">About Bottle</p>
+<p>This is my first open source project so far. It started and a small experiment but soon got so much positive feedback I decided to make something real out of it. Here it is.</p>
+<p class="rubric">Impressum und Kontaktdaten</p>
+<p>(This is required by <a class="reference external" href="http://bundesrecht.juris.de/tmg/__5.html">German law</a>)</p>
+<p>Die Nutzung der folgenden Kontaktdaten ist ausschließlich für die
+Kontaktaufnahme mit dem Betreiber dieser Webseite bei rechtlichen
+Problemen vorgesehen. Insbesondere die Nutzung zu Werbe- oder ähnlichen
+Zwecken ist ausdrücklich untersagt.</p>
+<blockquote>
+<div><ul class="simple">
+<li><strong>Betreiber</strong>: Marcel Hellkamp</li>
+<li><strong>Ort</strong>: D - 37075 Göttingen</li>
+<li><strong>Strasse</strong>: Theodor-Heuss Strasse 13</li>
+<li><strong>Telefon</strong>: +49 (0) 551 20005915</li>
+<li><strong>E-Mail</strong>: marc at gsites dot de</li>
+</ul>
+</div></blockquote>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/contact.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_contact';
+      var disqus_title = 'Contact';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="#">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/deployment.html b/html/deployment.html
new file mode 100644 (file)
index 0000000..ec4e1d6
--- /dev/null
@@ -0,0 +1,393 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Deployment &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="deployment">
+<span id="tutorial-deployment"></span><h1>Deployment<a class="headerlink" href="#deployment" title="Permalink to this headline">¶</a></h1>
+<p>The bottle <tt class="xref py py-func docutils literal"><span class="pre">run()</span></tt> function, when called without any parameters, starts a local development server on port 8080. You can access and test your application via <a class="reference external" href="http://localhost:8080/">http://localhost:8080/</a> if you are on the same host.</p>
+<p>To get your application available to the outside world, specify the IP of the interface the server should listen to (e.g. <tt class="docutils literal"><span class="pre">run(host='192.168.0.1')</span></tt>) or let the server listen to all interfaces at once (e.g. <tt class="docutils literal"><span class="pre">run(host='0.0.0.0')</span></tt>). The listening port can be changed in a similar way, but you need root or admin rights to choose a port below 1024. Port 80 is the standard for HTTP servers:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;0.0.0.0&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">80</span><span class="p">)</span> <span class="c"># Listen to HTTP requests on all interfaces</span>
+</pre></div>
+</div>
+<div class="section" id="server-options">
+<h2>Server Options<a class="headerlink" href="#server-options" title="Permalink to this headline">¶</a></h2>
+<p>The built-in default server is based on <a class="reference external" href="http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server">wsgiref WSGIServer</a>. This non-threading HTTP server is perfectly fine for development and early production, but may become a performance bottleneck when server load increases. There are three ways to eliminate this bottleneck:</p>
+<ul class="simple">
+<li>Use a different server that is either multi-threaded or asynchronous.</li>
+<li>Start multiple server processes and spread the load with a load-balancer.</li>
+<li>Do both.</li>
+</ul>
+<p><strong>Multi-threaded</strong> servers are the &#8216;classic&#8217; way to do it. They are very robust, reasonably fast and easy to manage. As a drawback, they can only handle a limited number of connections at the same time and utilize only one CPU core due to the &#8220;Global Interpreter Lock&#8221; (GIL). This does not hurt most applications, they are waiting for network IO most of the time anyway, but may slow down CPU intensive tasks (e.g. image processing).</p>
+<p><strong>Asynchronous</strong> servers are very fast, can handle a virtually unlimited number of concurrent connections and are easy to manage, but can get a bit tricky. To take full advantage of their potential, you need to design your application accordingly and understand the concepts of the specific server.</p>
+<p><strong>Multi-processing</strong> (forking) servers are not limited by the GIL and utilize more than one CPU core, but make communication between server instances more expensive. You need a database or external message query to share state between processes, or design your application so that it does not need any shared state. The setup is also a bit more complicated, but there are good tutorials available.</p>
+</div>
+<div class="section" id="switching-the-server-backend">
+<h2>Switching the Server Backend<a class="headerlink" href="#switching-the-server-backend" title="Permalink to this headline">¶</a></h2>
+<p>The easiest way to increase performance is to install a multi-threaded server library like <a class="reference external" href="http://pythonpaste.org/">paste</a> or <a class="reference external" href="http://www.cherrypy.org/">cherrypy</a> and tell Bottle to use that instead of the single-threaded server:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="s">&#39;paste&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Bottle ships with a lot of ready-to-use adapters for the most common WSGI servers and automates the setup process. Here is an incomplete list:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="11%" />
+<col width="16%" />
+<col width="73%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Name</th>
+<th class="head">Homepage</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>cgi</td>
+<td>&nbsp;</td>
+<td>Run as CGI script</td>
+</tr>
+<tr class="row-odd"><td>flup</td>
+<td><a class="reference external" href="http://trac.saddi.com/flup">flup</a></td>
+<td>Run as FastCGI process</td>
+</tr>
+<tr class="row-even"><td>gae</td>
+<td><a class="reference external" href="http://code.google.com/appengine/docs/python/overview.html">gae</a></td>
+<td>Helper for Google App Engine deployments</td>
+</tr>
+<tr class="row-odd"><td>wsgiref</td>
+<td><a class="reference external" href="http://docs.python.org/library/wsgiref.html">wsgiref</a></td>
+<td>Single-threaded default server</td>
+</tr>
+<tr class="row-even"><td>cherrypy</td>
+<td><a class="reference external" href="http://www.cherrypy.org/">cherrypy</a></td>
+<td>Multi-threaded and very stable</td>
+</tr>
+<tr class="row-odd"><td>paste</td>
+<td><a class="reference external" href="http://pythonpaste.org/">paste</a></td>
+<td>Multi-threaded, stable, tried and tested</td>
+</tr>
+<tr class="row-even"><td>rocket</td>
+<td><a class="reference external" href="http://pypi.python.org/pypi/rocket">rocket</a></td>
+<td>Multi-threaded</td>
+</tr>
+<tr class="row-odd"><td>waitress</td>
+<td><a class="reference external" href="http://readthedocs.org/docs/waitress/en/latest/">waitress</a></td>
+<td>Multi-threaded, poweres Pyramid</td>
+</tr>
+<tr class="row-even"><td>gunicorn</td>
+<td><a class="reference external" href="http://pypi.python.org/pypi/gunicorn">gunicorn</a></td>
+<td>Pre-forked, partly written in C</td>
+</tr>
+<tr class="row-odd"><td>eventlet</td>
+<td><a class="reference external" href="http://eventlet.net/">eventlet</a></td>
+<td>Asynchronous framework with WSGI support.</td>
+</tr>
+<tr class="row-even"><td>gevent</td>
+<td><a class="reference external" href="http://www.gevent.org/">gevent</a></td>
+<td>Asynchronous (greenlets)</td>
+</tr>
+<tr class="row-odd"><td>diesel</td>
+<td><a class="reference external" href="http://dieselweb.org/">diesel</a></td>
+<td>Asynchronous (greenlets)</td>
+</tr>
+<tr class="row-even"><td>fapws3</td>
+<td><a class="reference external" href="http://www.fapws.org/">fapws3</a></td>
+<td>Asynchronous (network side only), written in C</td>
+</tr>
+<tr class="row-odd"><td>tornado</td>
+<td><a class="reference external" href="http://www.tornadoweb.org/">tornado</a></td>
+<td>Asynchronous, powers some parts of Facebook</td>
+</tr>
+<tr class="row-even"><td>twisted</td>
+<td><a class="reference external" href="http://twistedmatrix.com/">twisted</a></td>
+<td>Asynchronous, well tested but... twisted</td>
+</tr>
+<tr class="row-odd"><td>meinheld</td>
+<td><a class="reference external" href="http://pypi.python.org/pypi/meinheld">meinheld</a></td>
+<td>Asynchronous, partly written in C</td>
+</tr>
+<tr class="row-even"><td>bjoern</td>
+<td><a class="reference external" href="http://pypi.python.org/pypi/bjoern">bjoern</a></td>
+<td>Asynchronous, very fast and written in C</td>
+</tr>
+<tr class="row-odd"><td>auto</td>
+<td>&nbsp;</td>
+<td>Automatically selects an available server adapter</td>
+</tr>
+</tbody>
+</table>
+<p>The full list is available through <tt class="xref py py-data docutils literal"><span class="pre">server_names</span></tt>.</p>
+<p>If there is no adapter for your favorite server or if you need more control over the server setup, you may want to start the server manually. Refer to the server documentation on how to run WSGI applications. Here is an example for <a class="reference external" href="http://pythonpaste.org/">paste</a>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">application</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">default_app</span><span class="p">()</span>
+<span class="kn">from</span> <span class="nn">paste</span> <span class="kn">import</span> <span class="n">httpserver</span>
+<span class="n">httpserver</span><span class="o">.</span><span class="n">serve</span><span class="p">(</span><span class="n">application</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="s">&#39;0.0.0.0&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">80</span><span class="p">)</span>
+</pre></div>
+</div>
+<div class="section" id="apache-mod-wsgi">
+<h3>Apache mod_wsgi<a class="headerlink" href="#apache-mod-wsgi" title="Permalink to this headline">¶</a></h3>
+<p>Instead of running your own HTTP server from within Bottle, you can attach Bottle applications to an <a class="reference external" href="apache">Apache server</a> using <a class="reference external" href="http://code.google.com/p/modwsgi/">mod_wsgi</a>.</p>
+<p>All you need is an <tt class="docutils literal"><span class="pre">app.wsgi</span></tt> file that provides an <tt class="docutils literal"><span class="pre">application</span></tt> object. This object is used by mod_wsgi to start your application and should be a WSGI-compatible Python callable.</p>
+<p>File <tt class="docutils literal"><span class="pre">/var/www/yourapp/app.wsgi</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="c"># Change working directory so relative paths (and template lookup) work again</span>
+<span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">))</span>
+
+<span class="kn">import</span> <span class="nn">bottle</span>
+<span class="c"># ... build or import your bottle application here ...</span>
+<span class="c"># Do NOT use bottle.run() with mod_wsgi</span>
+<span class="n">application</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">default_app</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>The Apache configuration may look like this:</p>
+<div class="highlight-python"><pre>&lt;VirtualHost *&gt;
+    ServerName example.com
+
+    WSGIDaemonProcess yourapp user=www-data group=www-data processes=1 threads=5
+    WSGIScriptAlias / /var/www/yourapp/app.wsgi
+
+    &lt;Directory /var/www/yourapp&gt;
+        WSGIProcessGroup yourapp
+        WSGIApplicationGroup %{GLOBAL}
+        Order deny,allow
+        Allow from all
+    &lt;/Directory&gt;
+&lt;/VirtualHost&gt;</pre>
+</div>
+</div>
+<div class="section" id="google-appengine">
+<h3>Google AppEngine<a class="headerlink" href="#google-appengine" title="Permalink to this headline">¶</a></h3>
+<p class="versionadded">
+<span class="versionmodified">New in version 0.9.</span></p>
+<p>The <tt class="docutils literal"><span class="pre">gae</span></tt> server adapter is used to run applications on Google App Engine. It works similar to the <tt class="docutils literal"><span class="pre">cgi</span></tt> adapter in that it does not start a new HTTP server, but prepares and optimizes your application for Google App Engine and makes sure it conforms to their API:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="s">&#39;gae&#39;</span><span class="p">)</span> <span class="c"># No need for a host or port setting.</span>
+</pre></div>
+</div>
+<p>It is always a good idea to let GAE serve static files directly. Here is example for a working  <tt class="docutils literal"><span class="pre">app.yaml</span></tt>:</p>
+<div class="highlight-python"><pre>application: myapp
+version: 1
+runtime: python
+api_version: 1
+
+handlers:
+- url: /static
+  static_dir: static
+
+- url: /.*
+  script: myapp.py</pre>
+</div>
+</div>
+<div class="section" id="load-balancer-manual-setup">
+<h3>Load Balancer (Manual Setup)<a class="headerlink" href="#load-balancer-manual-setup" title="Permalink to this headline">¶</a></h3>
+<p>A single Python process can utilize only one CPU at a time, even if there are more CPU cores available. The trick is to balance the load between multiple independent Python processes to utilize all of your CPU cores.</p>
+<p>Instead of a single Bottle application server, you start one instance for each CPU core available using different local port (localhost:8080, 8081, 8082, ...). You can choose any server adapter you want, even asynchronous ones. Then a high performance load balancer acts as a reverse proxy and forwards each new requests to a random port, spreading the load between all available back-ends. This way you can use all of your CPU cores and even spread out the load between different physical servers.</p>
+<p>One of the fastest load balancers available is <a class="reference external" href="http://www.apsis.ch/pound">Pound</a> but most common web servers have a proxy-module that can do the work just fine.</p>
+<p>Pound example:</p>
+<div class="highlight-python"><pre>ListenHTTP
+    Address 0.0.0.0
+    Port    80
+
+    Service
+        BackEnd
+            Address 127.0.0.1
+            Port    8080
+        End
+        BackEnd
+            Address 127.0.0.1
+            Port    8081
+        End
+    End
+End</pre>
+</div>
+<p>Apache example:</p>
+<div class="highlight-python"><pre>&lt;Proxy balancer://mycluster&gt;
+BalancerMember http://192.168.1.50:80
+BalancerMember http://192.168.1.51:80
+&lt;/Proxy&gt;
+ProxyPass / balancer://mycluster</pre>
+</div>
+<p>Lighttpd example:</p>
+<div class="highlight-python"><pre>server.modules += ( "mod_proxy" )
+proxy.server = (
+    "" =&gt; (
+        "wsgi1" =&gt; ( "host" =&gt; "127.0.0.1", "port" =&gt; 8080 ),
+        "wsgi2" =&gt; ( "host" =&gt; "127.0.0.1", "port" =&gt; 8081 )
+    )
+)</pre>
+</div>
+</div>
+</div>
+<div class="section" id="good-old-cgi">
+<h2>Good old CGI<a class="headerlink" href="#good-old-cgi" title="Permalink to this headline">¶</a></h2>
+<p>A CGI server starts a new process for each request. This adds a lot of overhead but is sometimes the only option, especially on cheap hosting packages. The <cite>cgi</cite> server adapter does not actually start a CGI server, but transforms your bottle application into a valid CGI application:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="s">&#39;cgi&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Deployment</a><ul>
+<li><a class="reference internal" href="#server-options">Server Options</a></li>
+<li><a class="reference internal" href="#switching-the-server-backend">Switching the Server Backend</a><ul>
+<li><a class="reference internal" href="#apache-mod-wsgi">Apache mod_wsgi</a></li>
+<li><a class="reference internal" href="#google-appengine">Google AppEngine</a></li>
+<li><a class="reference internal" href="#load-balancer-manual-setup">Load Balancer (Manual Setup)</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#good-old-cgi">Good old CGI</a></li>
+</ul>
+</li>
+</ul>
+
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/deployment.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_deployment';
+      var disqus_title = 'Deployment';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/development.html b/html/development.html
new file mode 100644 (file)
index 0000000..4e78ba9
--- /dev/null
@@ -0,0 +1,328 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Developer Notes &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Plugin Development Guide" href="plugindev.html" />
+    <link rel="prev" title="Release Notes and Changelog" href="changelog.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="plugindev.html" title="Plugin Development Guide"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="changelog.html" title="Release Notes and Changelog"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="developer-notes">
+<h1>Developer Notes<a class="headerlink" href="#developer-notes" title="Permalink to this headline">¶</a></h1>
+<p>This document is intended for developers and package maintainers interested in the bottle development and release workflow. If you want to contribute, you are just right!</p>
+<div class="section" id="get-involved">
+<h2>Get involved<a class="headerlink" href="#get-involved" title="Permalink to this headline">¶</a></h2>
+<p>There are several ways to join the community and stay up to date. Here are some of them:</p>
+<ul class="simple">
+<li><strong>Mailing list</strong>: Join our mailing list by sending an email to <a class="reference external" href="mailto:bottlepy+subscribe&#37;&#52;&#48;googlegroups&#46;com">bottlepy+subscribe<span>&#64;</span>googlegroups<span>&#46;</span>com</a> (no google account required).</li>
+<li><strong>Twitter</strong>: <a class="reference external" href="twitter.com/bottlepy">Follow us on Twitter</a> or search for the <a class="reference external" href="https://twitter.com/#!/search/%23bottlepy">#bottlepy</a> tag.</li>
+<li><strong>IRC</strong>: Join <a class="reference external" href="irc://irc.freenode.net/bottlepy">#bottlepy on irc.freenode.net</a> or use the <a class="reference external" href="http://webchat.freenode.net/?channels=bottlepy">web chat interface</a>.</li>
+<li><strong>Google plus</strong>: We sometimes <a class="reference external" href="https://plus.google.com/b/104025895326575643538/104025895326575643538/posts">blog about Bottle, releases and technical stuff</a> on our Google+ page.</li>
+</ul>
+</div>
+<div class="section" id="get-the-sources">
+<h2>Get the Sources<a class="headerlink" href="#get-the-sources" title="Permalink to this headline">¶</a></h2>
+<p>The bottle <a class="reference external" href="https://github.com/defnull/bottle">development repository</a> and the <a class="reference external" href="https://github.com/defnull/bottle/issues">issue tracker</a> are both hosted at <a class="reference external" href="https://github.com/defnull/bottle">github</a>. If you plan to contribute, it is a good idea to create an account there and fork the main repository. This way your changes and ideas are visible to other developers and can be discussed openly. Even without an account, you can clone the repository or just download the latest development version as a source archive.</p>
+<ul class="simple">
+<li><strong>git:</strong> <tt class="docutils literal"><span class="pre">git</span> <span class="pre">clone</span> <span class="pre">git://github.com/defnull/bottle.git</span></tt></li>
+<li><strong>git/https:</strong> <tt class="docutils literal"><span class="pre">git</span> <span class="pre">clone</span> <span class="pre">https://github.com/defnull/bottle.git</span></tt></li>
+<li><strong>Download:</strong> Development branch as <a class="reference external" href="http://github.com/defnull/bottle/tarball/master">tar archive</a> or <a class="reference external" href="http://github.com/defnull/bottle/zipball/master">zip file</a>.</li>
+</ul>
+</div>
+<div class="section" id="releases-and-updates">
+<h2>Releases and Updates<a class="headerlink" href="#releases-and-updates" title="Permalink to this headline">¶</a></h2>
+<p>Bottle is released at irregular intervals and distributed through <a class="reference external" href="http://pypi.python.org/pypi/bottle">PyPi</a>. Release candidates and bugfix-revisions of outdated releases are only available from the git repository mentioned above. Some Linux distributions may offer packages for outdated releases, though.</p>
+<p>The Bottle version number splits into three parts (<strong>major.minor.revision</strong>). These are <em>not</em> used to promote new features but to indicate important bug-fixes and/or API changes. Critical bugs are fixed in at least the two latest minor releases and announced in all available channels (mailinglist, twitter, github). Non-critical bugs or features are not guaranteed to be backported. This may change in the future, through.</p>
+<dl class="docutils">
+<dt>Major Release (x.0)</dt>
+<dd>The major release number is increased on important milestones or updates that completely break backward compatibility. You probably have to work over your entire application to use a new release. These releases are very rare, through.</dd>
+<dt>Minor Release (x.y)</dt>
+<dd>The minor release number is increased on updates that change the API or behaviour in some way. You might get some depreciation warnings any may have to tweak some configuration settings to restore the old behaviour, but in most cases these changes are designed to be backward compatible for at least one minor release. You should update to stay up do date, but don&#8217;t have to. An exception is 0.8, which <em>will</em> break backward compatibility hard. (This is why 0.7 was skipped). Sorry about that.</dd>
+<dt>Revision (x.y.z)</dt>
+<dd>The revision number is increased on bug-fixes and other patches that do not change the API or behaviour. You can safely update without editing your application code. In fact, you really should as soon as possible, because important security fixes are released this way.</dd>
+<dt>Pre-Release Versions</dt>
+<dd>Release candidates are marked by an <tt class="docutils literal"><span class="pre">rc</span></tt> in their revision number. These are API stable most of the time and open for testing, but not officially released yet. You should not use these for production.</dd>
+</dl>
+</div>
+<div class="section" id="repository-structure">
+<h2>Repository Structure<a class="headerlink" href="#repository-structure" title="Permalink to this headline">¶</a></h2>
+<p>The source repository is structured as follows:</p>
+<dl class="docutils">
+<dt><tt class="docutils literal"><span class="pre">master</span></tt> branch</dt>
+<dd>This is the integration, testing and development branch. All changes that are planned to be part of the next release are merged and tested here.</dd>
+<dt><tt class="docutils literal"><span class="pre">release-x.y</span></tt> branches</dt>
+<dd>As soon as the master branch is (almost) ready for a new release, it is branched into a new release branch. This &#8220;release candidate&#8221; is feature-frozen but may receive bug-fixes and last-minute changes until it is considered production ready and officially released. From that point on it is called a &#8220;support branch&#8221; and still receives bug-fixes, but only important ones. The revision number is increased on each push to these branches, so you can keep up with important changes.</dd>
+<dt><tt class="docutils literal"><span class="pre">bugfix_name-x.y</span></tt> branches</dt>
+<dd>These branches are only temporary and used to develop and share non-trivial bug-fixes for existing releases. They are merged into the corresponding release branch and deleted soon after that.</dd>
+<dt>Feature branches</dt>
+<dd>All other branches are feature branches. These are based on the master branch and only live as long as they are still active and not merged back into <tt class="docutils literal"><span class="pre">master</span></tt>.</dd>
+</dl>
+<p class="rubric">What does this mean for a developer?</p>
+<p>If you want to add a feature, create a new branch from <tt class="docutils literal"><span class="pre">master</span></tt>. If you want to fix a bug, branch <tt class="docutils literal"><span class="pre">release-x.y</span></tt> for each affected release. Please use a separate branch for each feature or bug to make integration as easy as possible. Thats all. There are git workflow examples at the bottom of this page.</p>
+<p>Oh, and never ever change the release number. We&#8217;ll do that on integration. You never know in which order we pull pending requests anyway :)</p>
+<p class="rubric">What does this mean for a maintainer ?</p>
+<p>Watch the tags (and the mailing list) for bug-fixes and new releases. If you want to fetch a specific release from the git repository, trust the tags, not the branches. A branch may contain changes that are not released yet, but a tag marks the exact commit which changed the version number.</p>
+</div>
+<div class="section" id="submitting-patches">
+<h2>Submitting Patches<a class="headerlink" href="#submitting-patches" title="Permalink to this headline">¶</a></h2>
+<p>The best way to get your changes integrated into the main development branch is to fork the main repository at github, create a new feature-branch, apply your changes and send a pull-request. Further down this page is a small collection of git workflow examples that may guide you. Submitting git-compatible patches to the mailing list is fine too. In any case, please follow some basic rules:</p>
+<ul class="simple">
+<li><strong>Documentation:</strong> Tell us what your patch does. Comment your code. If you introduced a new feature, add to the documentation so others can learn about it.</li>
+<li><strong>Test:</strong> Write tests to prove that your code works as expected and does not break anything. If you fixed a bug, write at least one test-case that triggers the bug. Make sure that all tests pass before you submit a patch.</li>
+<li><strong>One patch at a time:</strong> Only fix one bug or add one feature at a time. Design your patches so that they can be applyed as a whole. Keep your patches clean, small and focused.</li>
+<li><strong>Sync with upstream:</strong> If the <tt class="docutils literal"><span class="pre">upstream/master</span></tt> branch changed while you were working on your patch, rebase or pull to make sure that your patch still applies without conflicts.</li>
+</ul>
+</div>
+<div class="section" id="building-the-documentation">
+<h2>Building the Documentation<a class="headerlink" href="#building-the-documentation" title="Permalink to this headline">¶</a></h2>
+<p>You need a recent version of Sphinx to build the documentation. The recommended way is to install <strong class="command">virtualenv</strong> using your distribution package repository and install sphinx manually to get an up-to-date version.</p>
+<div class="highlight-bash"><div class="highlight"><pre><span class="c"># Install prerequisites</span>
+which virtualenv <span class="o">||</span> sudo apt-get install python-virtualenv
+virtualenv --no-site-dependencies venv
+./venv/pip install -U sphinx
+
+<span class="c"># Clone or download bottle from github</span>
+git clone https://github.com/defnull/bottle.git
+
+<span class="c"># Activate build environment</span>
+<span class="nb">source</span> ./venv/bin/activate
+
+<span class="c"># Build HTML docs</span>
+<span class="nb">cd </span>bottle/docs
+make html
+
+<span class="c"># Optional: Install prerequisites for PDF generation</span>
+sudo apt-get install texlive-latex-extra <span class="se">\</span>
+                     texlive-latex-recommended <span class="se">\</span>
+                     texlive-fonts-recommended
+
+<span class="c"># Optional: Build the documentation as PDF</span>
+make latex
+<span class="nb">cd</span> ../build/docs/latex
+make pdf
+</pre></div>
+</div>
+</div>
+<div class="section" id="git-workflow-examples">
+<h2>GIT Workflow Examples<a class="headerlink" href="#git-workflow-examples" title="Permalink to this headline">¶</a></h2>
+<p>The following examples assume that you have an (free) <a class="reference external" href="https://github.com">github account</a>. This is not mandatory, but makes things a lot easier.</p>
+<p>First of all you need to create a fork (a personal clone) of the official repository. To do this, you simply click the &#8220;fork&#8221; button on the <a class="reference external" href="https://github.com/defnull/bottle">bottle project page</a>. When the fork is done, you will be presented with a short introduction to your new repository.</p>
+<p>The fork you just created is hosted at github and read-able by everyone, but write-able only by you. Now you need to clone the fork locally to actually make changes to it. Make sure you use the private (read-write) URL and <em>not</em> the public (read-only) one:</p>
+<div class="highlight-python"><pre>git clone git@github.com:your_github_account/bottle.git</pre>
+</div>
+<p>Once the clone is complete your repository will have a remote named &#8220;origin&#8221; that points to your fork on github. Don’t let the name confuse you, this does not point to the original bottle repository, but to your own fork. To keep track of the official repository, add another remote named &#8220;upstream&#8221;:</p>
+<div class="highlight-python"><pre>cd bottle
+git remote add upstream git://github.com/defnull/bottle.git
+git fetch upstream</pre>
+</div>
+<p>Note that &#8220;upstream&#8221; is a public clone URL, which is read-only. You cannot push changes directly to it. Instead, we will pull from your public repository. This is described later.</p>
+<p class="rubric">Submit a Feature</p>
+<p>New features are developed in separate feature-branches to make integration easy. Because they are going to be integrated into the <tt class="docutils literal"><span class="pre">master</span></tt> branch, they must be based on <tt class="docutils literal"><span class="pre">upstream/master</span></tt>. To create a new feature-branch, type the following:</p>
+<div class="highlight-python"><pre>git checkout -b cool_feature upstream/master</pre>
+</div>
+<p>Now implement your feature, write tests, update the documentation, make sure that all tests pass and commit your changes:</p>
+<div class="highlight-python"><pre>git commit -a -m "Cool Feature"</pre>
+</div>
+<p>If the <tt class="docutils literal"><span class="pre">upstream/master</span></tt> branch changed in the meantime, there may be conflicts with your changes. To solve these, &#8216;rebase&#8217; your feature-branch onto the top of the updated <tt class="docutils literal"><span class="pre">upstream/master</span></tt> branch:</p>
+<div class="highlight-python"><pre>git fetch upstream
+git rebase upstream</pre>
+</div>
+<p>This is equivalent to undoing all your changes, updating your branch to the latest version and reapplying all your patches again. If you released your branch already (see next step), this is not an option because it rewrites your history. You can do a normal pull instead. Resolve any conflicts, run the tests again and commit.</p>
+<p>Now you are almost ready to send a pull request. But first you need to make your feature-branch public by pushing it to your github fork:</p>
+<div class="highlight-python"><pre>git push origin cool_feature</pre>
+</div>
+<p>After you’ve pushed your commit(s) you need to inform us about the new feature. One way is to send a pull-request using github. Another way would be to start a thread in the mailing-list, which is recommended. It allows other developers to see and discuss your patches and you get some feedback for free :)</p>
+<p>If we accept your patch, we will integrate it into the official development branch and make it part of the next release.</p>
+<p class="rubric">Fix a Bug</p>
+<p>The workflow for bug-fixes is very similar to the one for features, but there are some differences:</p>
+<ol class="arabic simple">
+<li>Branch off of the affected release branches instead of just the development branch.</li>
+<li>Write at least one test-case that triggers the bug.</li>
+<li>Do this for each affected branch including <tt class="docutils literal"><span class="pre">upstream/master</span></tt> if it is affected. <tt class="docutils literal"><span class="pre">git</span> <span class="pre">cherry-pick</span></tt> may help you reducing repetitive work.</li>
+<li>Name your branch after the release it is based on to avoid confusion. Examples: <tt class="docutils literal"><span class="pre">my_bugfix-x.y</span></tt> or <tt class="docutils literal"><span class="pre">my_bugfix-dev</span></tt>.</li>
+</ol>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Developer Notes</a><ul>
+<li><a class="reference internal" href="#get-involved">Get involved</a></li>
+<li><a class="reference internal" href="#get-the-sources">Get the Sources</a></li>
+<li><a class="reference internal" href="#releases-and-updates">Releases and Updates</a></li>
+<li><a class="reference internal" href="#repository-structure">Repository Structure</a></li>
+<li><a class="reference internal" href="#submitting-patches">Submitting Patches</a></li>
+<li><a class="reference internal" href="#building-the-documentation">Building the Documentation</a></li>
+<li><a class="reference internal" href="#git-workflow-examples">GIT Workflow Examples</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="changelog.html"
+                        title="previous chapter">Release Notes and Changelog</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="plugindev.html"
+                        title="next chapter">Plugin Development Guide</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/development.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="plugindev.html" title="Plugin Development Guide"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="changelog.html" title="Release Notes and Changelog"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_development';
+      var disqus_title = 'Developer Notes';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/faq.html b/html/faq.html
new file mode 100644 (file)
index 0000000..0328d76
--- /dev/null
@@ -0,0 +1,235 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Frequently Asked Questions &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Release Notes and Changelog" href="changelog.html" />
+    <link rel="prev" title="Recipes" href="recipes.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="changelog.html" title="Release Notes and Changelog"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="recipes.html" title="Recipes"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <span class="target" id="module-bottle"></span><div class="section" id="frequently-asked-questions">
+<h1>Frequently Asked Questions<a class="headerlink" href="#frequently-asked-questions" title="Permalink to this headline">¶</a></h1>
+<div class="section" id="about-bottle">
+<h2>About Bottle<a class="headerlink" href="#about-bottle" title="Permalink to this headline">¶</a></h2>
+<div class="section" id="is-bottle-suitable-for-complex-applications">
+<h3>Is bottle suitable for complex applications?<a class="headerlink" href="#is-bottle-suitable-for-complex-applications" title="Permalink to this headline">¶</a></h3>
+<p>Bottle is a <em>micro</em> framework designed for prototyping and building small web applications and services. It stays out of your way and allows you to get things done fast, but misses some advanced features and ready-to-use solutions found in other frameworks (MVC, ORM, form validation, scaffolding, XML-RPC). Although it <em>is</em> possible to add these features and build complex applications with Bottle, you should consider using a full-stack Web framework like <a class="reference external" href="http://pylonshq.com/">pylons</a> or <a class="reference external" href="http://pythonpaste.org/modules/evalexception.html">paste</a> instead.</p>
+</div>
+</div>
+<div class="section" id="common-problems-and-pitfalls">
+<h2>Common Problems and Pitfalls<a class="headerlink" href="#common-problems-and-pitfalls" title="Permalink to this headline">¶</a></h2>
+<div class="section" id="template-not-found-in-mod-wsgi-mod-python">
+<h3>&#8220;Template Not Found&#8221; in mod_wsgi/mod_python<a class="headerlink" href="#template-not-found-in-mod-wsgi-mod-python" title="Permalink to this headline">¶</a></h3>
+<p>Bottle searches in <tt class="docutils literal"><span class="pre">./</span></tt> and <tt class="docutils literal"><span class="pre">./views/</span></tt> for templates. In a <a class="reference external" href="http://www.modpython.org/">mod_python</a> or <a class="reference external" href="http://code.google.com/p/modwsgi/">mod_wsgi</a> environment, the working directory (<tt class="docutils literal"><span class="pre">./</span></tt>) depends on your Apache settings. You should add an absolute path to the template search path:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">bottle</span><span class="o">.</span><span class="n">TEMPLATE_PATH</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="s">&#39;/absolut/path/to/templates/&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>so bottle searches the right paths.</p>
+</div>
+<div class="section" id="dynamic-routes-and-slashes">
+<h3>Dynamic Routes and Slashes<a class="headerlink" href="#dynamic-routes-and-slashes" title="Permalink to this headline">¶</a></h3>
+<p>In <a class="reference internal" href="tutorial.html#tutorial-dynamic-routes"><em>dynamic route syntax</em></a>, a placeholder token (<tt class="docutils literal"><span class="pre">:name</span></tt>) matches everything up to the next slash. This equals to <tt class="docutils literal"><span class="pre">[^/]+</span></tt> in regular expression syntax. To accept slashes too, you have to add a custom regular pattern to the placeholder. An example: <tt class="docutils literal"><span class="pre">/images/:filepath#.*#</span></tt> would match <tt class="docutils literal"><span class="pre">/images/icons/error.png</span></tt> but <tt class="docutils literal"><span class="pre">/images/:filename</span></tt> won&#8217;t.</p>
+</div>
+<div class="section" id="problems-with-reverse-proxies">
+<h3>Problems with reverse proxies<a class="headerlink" href="#problems-with-reverse-proxies" title="Permalink to this headline">¶</a></h3>
+<p>Redirects and url-building only works if bottle knows the public address and location of your application. If you run bottle locally behind a reverse proxy or load balancer, some information might get lost along the way. For example, the <tt class="docutils literal"><span class="pre">wsgi.url_scheme</span></tt> value or the <tt class="docutils literal"><span class="pre">Host</span></tt> header might reflect the local request by your proxy, not the real request by the client. Here is a small WSGI middleware snippet that helps to fix these values:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">fix_environ_middleware</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
+  <span class="k">def</span> <span class="nf">fixed_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
+    <span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.url_scheme&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;https&#39;</span>
+    <span class="n">environ</span><span class="p">[</span><span class="s">&#39;HTTP_X_FORWARDED_HOST&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;example.com&#39;</span>
+    <span class="k">return</span> <span class="n">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
+  <span class="k">return</span> <span class="n">https_app</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">default_app</span><span class="p">()</span>
+<span class="n">app</span><span class="o">.</span><span class="n">wsgi</span> <span class="o">=</span> <span class="n">fix_environ_middleware</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">wsgi</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Frequently Asked Questions</a><ul>
+<li><a class="reference internal" href="#about-bottle">About Bottle</a><ul>
+<li><a class="reference internal" href="#is-bottle-suitable-for-complex-applications">Is bottle suitable for complex applications?</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#common-problems-and-pitfalls">Common Problems and Pitfalls</a><ul>
+<li><a class="reference internal" href="#template-not-found-in-mod-wsgi-mod-python">&#8220;Template Not Found&#8221; in mod_wsgi/mod_python</a></li>
+<li><a class="reference internal" href="#dynamic-routes-and-slashes">Dynamic Routes and Slashes</a></li>
+<li><a class="reference internal" href="#problems-with-reverse-proxies">Problems with reverse proxies</a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="recipes.html"
+                        title="previous chapter">Recipes</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="changelog.html"
+                        title="next chapter">Release Notes and Changelog</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/faq.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="changelog.html" title="Release Notes and Changelog"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="recipes.html" title="Recipes"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_faq';
+      var disqus_title = 'Frequently Asked Questions';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/genindex.html b/html/genindex.html
new file mode 100644 (file)
index 0000000..9f6fc32
--- /dev/null
@@ -0,0 +1,1094 @@
+
+
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Index &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="#" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+
+<h1 id="index">Index</h1>
+
+<div class="genindex-jumpbox">
+ <a href="#_"><strong>_</strong></a>
+ | <a href="#A"><strong>A</strong></a>
+ | <a href="#B"><strong>B</strong></a>
+ | <a href="#C"><strong>C</strong></a>
+ | <a href="#D"><strong>D</strong></a>
+ | <a href="#E"><strong>E</strong></a>
+ | <a href="#F"><strong>F</strong></a>
+ | <a href="#G"><strong>G</strong></a>
+ | <a href="#H"><strong>H</strong></a>
+ | <a href="#I"><strong>I</strong></a>
+ | <a href="#J"><strong>J</strong></a>
+ | <a href="#L"><strong>L</strong></a>
+ | <a href="#M"><strong>M</strong></a>
+ | <a href="#N"><strong>N</strong></a>
+ | <a href="#O"><strong>O</strong></a>
+ | <a href="#P"><strong>P</strong></a>
+ | <a href="#Q"><strong>Q</strong></a>
+ | <a href="#R"><strong>R</strong></a>
+ | <a href="#S"><strong>S</strong></a>
+ | <a href="#T"><strong>T</strong></a>
+ | <a href="#U"><strong>U</strong></a>
+ | <a href="#V"><strong>V</strong></a>
+ | <a href="#W"><strong>W</strong></a>
+ | <a href="#Y"><strong>Y</strong></a>
+</div>
+<h2 id="_">_</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="plugindev.html#bottle.Plugin.__call__">__call__() (Plugin method)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseTemplate.__init__">__init__() (BaseTemplate method)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="A">A</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseResponse.add_header">add_header() (BaseResponse method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.ResourceManager.add_path">add_path() (ResourceManager method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.add_route">add_route() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Route.all_plugins">all_plugins() (Route method)</a>
+  </dt>
+
+      
+  <dt><a href="plugindev.html#bottle.Plugin.api">api (Plugin attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.app">app (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.app">(Route attribute)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.app">app() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.MultiDict.append">append() (MultiDict method)</a>
+  </dt>
+
+      
+  <dt><a href="plugindev.html#bottle.Plugin.apply">apply() (Plugin method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.AppStack">AppStack (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.auth">auth (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="B">B</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest">BaseRequest (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse">BaseResponse (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseTemplate">BaseTemplate (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.LocalRequest.bind">bind() (LocalRequest method)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.body">body (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.LocalResponse.body">(LocalResponse attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.Bottle">Bottle (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="recipes.html#module-bottle">bottle (module)</a>, <a href="faq.html#module-bottle">[1]</a>, <a href="plugins/index.html#module-bottle">[2]</a>, <a href="api.html#module-bottle">[3]</a>, <a href="plugindev.html#module-bottle">[4]</a>, <a href="tutorial.html#module-bottle">[5]</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BottleException">BottleException</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="C">C</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.ResourceManager.cache">cache (ResourceManager attribute)</a>
+  </dt>
+
+      
+  <dt><a href="tutorial.html#term-callback"><strong>callback</strong></a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.callback">(Route attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.Bottle.catchall">catchall (Bottle attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.WSGIHeaderDict.cgikeys">cgikeys (WSGIHeaderDict attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.charset">charset (BaseResponse attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.close">close() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="plugindev.html#bottle.Plugin.close">(Plugin method)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.Bottle.config">config (Bottle attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.config">(Route attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.BaseRequest.content_length">content_length (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseResponse.content_length">(BaseResponse attribute)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.content_type">content_type (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseResponse.content_type">(BaseResponse attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.cookie_decode">cookie_decode() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.cookie_encode">cookie_encode() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.cookie_is_encoded">cookie_is_encoded() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.cookies">cookies (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.COOKIES">COOKIES (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseResponse.COOKIES">(BaseResponse attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.BaseRequest.copy">copy() (BaseRequest method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseResponse.copy">(BaseResponse method)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+</tr></table>
+
+<h2 id="D">D</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.debug">debug() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.FormsDict.decode">decode() (FormsDict method)</a>
+  </dt>
+
+      
+  <dt><a href="tutorial.html#term-decorator"><strong>decorator</strong></a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.default_app">default_app() (in module bottle)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="stpl.html#stpl.defined">defined() (in module stpl)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.delete">delete() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.delete">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.BaseResponse.delete_cookie">delete_cookie() (BaseResponse method)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="E">E</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="tutorial.html#term-environ"><strong>environ</strong></a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseRequest.environ">(BaseRequest attribute)</a>
+  </dt>
+
+        
+  <dt><a href="api.html#bottle.LocalRequest.environ">(LocalRequest attribute)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Bottle.error">error() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.error">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+</tr></table>
+
+<h2 id="F">F</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.files">files (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.forms">forms (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.FormsDict">FormsDict (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.fullpath">fullpath (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="G">G</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.GET">GET (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.get">get() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.MultiDict.get">(MultiDict method)</a>
+  </dt>
+
+        
+  <dt><a href="api.html#bottle.get">(in module bottle)</a>
+  </dt>
+
+        
+  <dt><a href="stpl.html#stpl.get">(in module stpl)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.BaseRequest.get_cookie">get_cookie() (BaseRequest method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.get_header">get_header() (BaseRequest method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseResponse.get_header">(BaseResponse method)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.Bottle.get_url">get_url() (Bottle method)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.MultiDict.getall">getall() (MultiDict method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.MultiDict.getlist">getlist() (MultiDict method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.MultiDict.getone">getone() (MultiDict method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseTemplate.global_config">global_config() (bottle.BaseTemplate class method)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="H">H</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Bottle.handle">handle() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="tutorial.html#term-handler-function"><strong>handler function</strong></a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.HeaderDict">HeaderDict (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.headerlist">headerlist (BaseResponse attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.headers">headers (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.BaseResponse.headers">(BaseResponse attribute)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Bottle.hook">hook() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.HTTP_CODES">HTTP_CODES (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.HTTPError">HTTPError</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.HTTPResponse">HTTPResponse</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="I">I</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.FormsDict.input_encoding">input_encoding (FormsDict attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.install">install() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.is_ajax">is_ajax (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.is_xhr">is_xhr (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.iter_headers">iter_headers() (BaseResponse method)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="J">J</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.json">json (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="L">L</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.load">load() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.load_app">load_app() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.LocalRequest">LocalRequest (class in bottle)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.LocalResponse">LocalResponse (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.ResourceManager.lookup">lookup() (ResourceManager method)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="M">M</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Bottle.match">match() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.MAX_PARAMS">MAX_PARAMS (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.MEMFILE_MAX">MEMFILE_MAX (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.merge">merge() (Bottle method)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.method">method (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.method">(Route attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.Bottle.mount">mount() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.MultiDict">MultiDict (class in bottle)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="N">N</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="plugindev.html#bottle.Plugin.name">name (Plugin attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.name">(Route attribute)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+</tr></table>
+
+<h2 id="O">O</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.ResourceManager.open">open() (ResourceManager method)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.HTTPResponse.output">output (HTTPResponse attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="P">P</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.params">params (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.parse_auth">parse_auth() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.parse_date">parse_date() (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.path">path (BaseRequest attribute)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.ResourceManager.path">(ResourceManager attribute)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.BaseRequest.path_shift">path_shift() (BaseRequest method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.path_shift">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="plugindev.html#bottle.Plugin">Plugin (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Route.plugins">plugins (Route attribute)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.AppStack.pop">pop() (AppStack method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.POST">POST (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.post">post() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.post">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.BaseTemplate.prepare">prepare() (BaseTemplate method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.prepare">(Route method)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.AppStack.push">push() (AppStack method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.put">put() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.put">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+</tr></table>
+
+<h2 id="Q">Q</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.query">query (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.query_string">query_string (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="R">R</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.WSGIHeaderDict.raw">raw() (WSGIHeaderDict method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.FormsDict.recode_unicode">recode_unicode (FormsDict attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.remote_addr">remote_addr (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.remote_route">remote_route (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseTemplate.render">render() (BaseTemplate method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="stpl.html#bottle.SimpleTemplate.render">(SimpleTemplate method)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.MultiDict.replace">replace() (MultiDict method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Request">Request (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.request">request (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.reset">reset() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.Route.reset">(Route method)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.ResourceManager">ResourceManager (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.resources">resources (Bottle attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.response">response (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Response">Response (in module bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Route">Route (class in bottle)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.route">route() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.route">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+      
+  <dt><a href="api.html#bottle.Route.rule">rule (Route attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.Bottle.run">run() (Bottle method)</a>
+  </dt>
+
+      <dd><dl>
+        
+  <dt><a href="api.html#bottle.run">(in module bottle)</a>
+  </dt>
+
+      </dl></dd>
+  </dl></td>
+</tr></table>
+
+<h2 id="S">S</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.script_name">script_name (BaseRequest attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseTemplate.search">search() (bottle.BaseTemplate class method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.set_cookie">set_cookie() (BaseResponse method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.set_header">set_header() (BaseResponse method)</a>
+  </dt>
+
+      
+  <dt><a href="stpl.html#stpl.setdefault">setdefault() (in module stpl)</a>
+  </dt>
+
+      
+  <dt><a href="plugindev.html#bottle.Plugin.setup">setup() (Plugin method)</a>
+  </dt>
+
+      
+  <dt><a href="stpl.html#bottle.SimpleTemplate">SimpleTemplate (class in bottle)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Route.skiplist">skiplist (Route attribute)</a>
+  </dt>
+
+      
+  <dt><a href="tutorial.html#term-source-directory"><strong>source directory</strong></a>
+  </dt>
+
+      
+  <dt><a href="stpl.html#bottle.SimpleTemplate.split_comment">split_comment() (bottle.SimpleTemplate class method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.status">status (BaseResponse attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.status_code">status_code (BaseResponse attribute)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseResponse.status_line">status_line (BaseResponse attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="T">T</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.template">template() (in module bottle)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="U">U</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Bottle.uninstall">uninstall() (Bottle method)</a>
+  </dt>
+
+      
+  <dt><a href="api.html#bottle.BaseRequest.url">url (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.BaseRequest.urlparts">urlparts (BaseRequest attribute)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="V">V</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.view">view() (in module bottle)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="W">W</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.Bottle.wsgi">wsgi() (Bottle method)</a>
+  </dt>
+
+  </dl></td>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.WSGIHeaderDict">WSGIHeaderDict (class in bottle)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+<h2 id="Y">Y</h2>
+<table style="width: 100%" class="indextable genindextable"><tr>
+  <td style="width: 33%" valign="top"><dl>
+      
+  <dt><a href="api.html#bottle.yieldroutes">yieldroutes() (in module bottle)</a>
+  </dt>
+
+  </dl></td>
+</tr></table>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  
+
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="#" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_genindex';
+      var disqus_title = 'Index';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/index.html b/html/index.html
new file mode 100644 (file)
index 0000000..34a8abd
--- /dev/null
@@ -0,0 +1,386 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Bottle: Python Web Framework &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="#" />
+    <link rel="next" title="Tutorial" href="tutorial.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    <meta name="description" content="Bottle is a fast, simple and lightweight WSGI micro web-framework for Python." />
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="tutorial.html" title="Tutorial"
+             accesskey="N">next</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="#">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="bottle-python-web-framework">
+<h1>Bottle: Python Web Framework<a class="headerlink" href="#bottle-python-web-framework" title="Permalink to this headline">¶</a></h1>
+<p>Bottle is a fast, simple and lightweight <a class="reference external" href="http://www.wsgi.org/wsgi/">WSGI</a> micro web-framework for <a class="reference external" href="http://python.org/">Python</a>. It is distributed as a single file module and has no dependencies other than the <a class="reference external" href="http://docs.python.org/library/">Python Standard Library</a>.</p>
+<ul class="simple">
+<li><strong>Routing:</strong> Requests to function-call mapping with support for clean and  dynamic URLs.</li>
+<li><strong>Templates:</strong> Fast and pythonic <a class="reference internal" href="tutorial.html#tutorial-templates"><em>built-in template engine</em></a> and support for <a class="reference external" href="http://www.makotemplates.org/">mako</a>, <a class="reference external" href="http://jinja.pocoo.org/2/">jinja2</a> and <a class="reference external" href="http://www.cheetahtemplate.org/">cheetah</a> templates.</li>
+<li><strong>Utilities:</strong> Convenient access to form data, file uploads, cookies, headers and other HTTP-related metadata.</li>
+<li><strong>Server:</strong> Built-in HTTP development server and support for <a class="reference external" href="http://pythonpaste.org/">paste</a>, <a class="reference external" href="https://github.com/william-os4y/fapws3">fapws3</a>, <a class="reference external" href="https://github.com/jonashaag/bjoern">bjoern</a>, <a class="reference external" href="http://code.google.com/intl/en-US/appengine/">Google App Engine</a>, <a class="reference external" href="http://www.cherrypy.org/">cherrypy</a> or any other <a class="reference external" href="http://www.wsgi.org/wsgi/">WSGI</a> capable HTTP server.</li>
+</ul>
+<p class="rubric">Example: &#8220;Hello World&#8221; in a bottle</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">template</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello/:name&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;World&#39;</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;&lt;b&gt;Hello {{name}}&lt;/b&gt;!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
+
+<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Run this script or paste it into a Python console, then point your browser to <a class="reference external" href="http://localhost:8080/hello/world">http://localhost:8080/hello/world</a>. That&#8217;s it.</p>
+<p class="rubric">Download and Install</p>
+<p>Install the latest stable release via <a class="reference external" href="http://pypi.python.org/pypi/bottle">PyPi</a> (<tt class="docutils literal"><span class="pre">easy_install</span> <span class="pre">-U</span> <span class="pre">bottle</span></tt>) or download <a class="reference external" href="https://github.com/defnull/bottle/raw/master/bottle.py">bottle.py</a> (unstable) into your project directory. There are no hard <a class="footnote-reference" href="#id3" id="id2">[1]</a> dependencies other than the Python standard library. Bottle runs with <strong>Python 2.5+ and 3.x</strong>.</p>
+<div class="section" id="user-s-guide">
+<h2>User&#8217;s Guide<a class="headerlink" href="#user-s-guide" title="Permalink to this headline">¶</a></h2>
+<p>Start here if you want to learn how to use the bottle framework for web development. If you have any questions not answered here, feel free to ask the <a class="reference external" href="mailto:bottlepy&#37;&#52;&#48;googlegroups&#46;com">mailing list</a>.</p>
+<div class="toctree-wrapper compound">
+<ul>
+<li class="toctree-l1"><a class="reference internal" href="tutorial.html">Tutorial</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#installation">Installation</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#quickstart-hello-world">Quickstart: &#8220;Hello World&#8221;</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#request-routing">Request Routing</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#generating-content">Generating content</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#request-data">Request Data</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#templates">Templates</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#plugins">Plugins</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#development">Development</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#deployment">Deployment</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial.html#glossary">Glossary</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="routing.html">Request Routing</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="routing.html#rule-syntax">Rule Syntax</a></li>
+<li class="toctree-l2"><a class="reference internal" href="routing.html#wildcard-filters">Wildcard Filters</a></li>
+<li class="toctree-l2"><a class="reference internal" href="routing.html#legacy-syntax">Legacy Syntax</a></li>
+<li class="toctree-l2"><a class="reference internal" href="routing.html#routing-order">Routing Order</a></li>
+<li class="toctree-l2"><a class="reference internal" href="routing.html#explicit-routing-configuration">Explicit routing configuration</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="stpl.html">SimpleTemplate Engine</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="stpl.html#simpletemplate-syntax"><tt class="docutils literal"><span class="pre">SimpleTemplate</span></tt> Syntax</a></li>
+<li class="toctree-l2"><a class="reference internal" href="stpl.html#simpletemplate-api"><tt class="docutils literal"><span class="pre">SimpleTemplate</span></tt> API</a></li>
+<li class="toctree-l2"><a class="reference internal" href="stpl.html#known-bugs">Known bugs</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="api.html">API Reference</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="api.html#module-contents">Module Contents</a></li>
+<li class="toctree-l2"><a class="reference internal" href="api.html#the-bottle-class">The <tt class="docutils literal"><span class="pre">Bottle</span></tt> Class</a></li>
+<li class="toctree-l2"><a class="reference internal" href="api.html#the-request-object">The <tt class="docutils literal"><span class="pre">Request</span></tt> Object</a></li>
+<li class="toctree-l2"><a class="reference internal" href="api.html#the-response-object">The <tt class="docutils literal"><span class="pre">Response</span></tt> Object</a></li>
+<li class="toctree-l2"><a class="reference internal" href="api.html#templates">Templates</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="plugins/index.html">List of available Plugins</a><ul>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="section" id="knowledge-base">
+<h2>Knowledge Base<a class="headerlink" href="#knowledge-base" title="Permalink to this headline">¶</a></h2>
+<p>A collection of articles, guides and HOWTOs.</p>
+<div class="toctree-wrapper compound">
+<ul>
+<li class="toctree-l1"><a class="reference internal" href="tutorial_app.html">Tutorial: Todo-List Application</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="tutorial_app.html#goals">Goals</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial_app.html#before-we-start">Before We Start...</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial_app.html#using-bottle-for-a-web-based-todo-list">Using Bottle for a Web-Based ToDo List</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial_app.html#server-setup">Server Setup</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial_app.html#final-words">Final Words</a></li>
+<li class="toctree-l2"><a class="reference internal" href="tutorial_app.html#complete-example-listing">Complete Example Listing</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="async.html">Primer to Asynchronous Applications</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="async.html#the-limits-of-synchronous-wsgi">The Limits of Synchronous WSGI</a></li>
+<li class="toctree-l2"><a class="reference internal" href="async.html#greenlets-to-the-rescue">Greenlets to the rescue</a></li>
+<li class="toctree-l2"><a class="reference internal" href="async.html#event-callbacks">Event Callbacks</a></li>
+<li class="toctree-l2"><a class="reference internal" href="async.html#finally-websockets">Finally: WebSockets</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="recipes.html">Recipes</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#keeping-track-of-sessions">Keeping track of Sessions</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#debugging-with-style-debugging-middleware">Debugging with Style: Debugging Middleware</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#unit-testing-bottle-applications">Unit-Testing Bottle Applications</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#functional-testing-bottle-applications">Functional Testing Bottle Applications</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#embedding-other-wsgi-apps">Embedding other WSGI Apps</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#ignore-trailing-slashes">Ignore trailing slashes</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#keep-alive-requests">Keep-alive requests</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#gzip-compression-in-bottle">Gzip Compression in Bottle</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#using-the-hooks-plugin">Using the hooks plugin</a></li>
+<li class="toctree-l2"><a class="reference internal" href="recipes.html#using-bottle-with-heroku">Using Bottle with Heroku</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="faq.html">Frequently Asked Questions</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="faq.html#about-bottle">About Bottle</a></li>
+<li class="toctree-l2"><a class="reference internal" href="faq.html#common-problems-and-pitfalls">Common Problems and Pitfalls</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="section" id="development-and-contribution">
+<h2>Development and Contribution<a class="headerlink" href="#development-and-contribution" title="Permalink to this headline">¶</a></h2>
+<p>These chapters are intended for developers interested in the bottle development and release workflow.</p>
+<div class="toctree-wrapper compound">
+<ul>
+<li class="toctree-l1"><a class="reference internal" href="changelog.html">Release Notes and Changelog</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="changelog.html#release-0-11">Release 0.11</a></li>
+<li class="toctree-l2"><a class="reference internal" href="changelog.html#release-0-10">Release 0.10</a></li>
+<li class="toctree-l2"><a class="reference internal" href="changelog.html#release-0-9">Release 0.9</a></li>
+<li class="toctree-l2"><a class="reference internal" href="changelog.html#release-0-8">Release 0.8</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="changelog.html#contributors">Contributors</a></li>
+<li class="toctree-l1"><a class="reference internal" href="development.html">Developer Notes</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="development.html#get-involved">Get involved</a></li>
+<li class="toctree-l2"><a class="reference internal" href="development.html#get-the-sources">Get the Sources</a></li>
+<li class="toctree-l2"><a class="reference internal" href="development.html#releases-and-updates">Releases and Updates</a></li>
+<li class="toctree-l2"><a class="reference internal" href="development.html#repository-structure">Repository Structure</a></li>
+<li class="toctree-l2"><a class="reference internal" href="development.html#submitting-patches">Submitting Patches</a></li>
+<li class="toctree-l2"><a class="reference internal" href="development.html#building-the-documentation">Building the Documentation</a></li>
+<li class="toctree-l2"><a class="reference internal" href="development.html#git-workflow-examples">GIT Workflow Examples</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="plugindev.html">Plugin Development Guide</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="plugindev.html#how-plugins-work-the-basics">How Plugins Work: The Basics</a></li>
+<li class="toctree-l2"><a class="reference internal" href="plugindev.html#plugin-api">Plugin API</a></li>
+<li class="toctree-l2"><a class="reference internal" href="plugindev.html#the-route-context">The Route Context</a></li>
+<li class="toctree-l2"><a class="reference internal" href="plugindev.html#runtime-optimizations">Runtime optimizations</a></li>
+<li class="toctree-l2"><a class="reference internal" href="plugindev.html#plugin-example-sqliteplugin">Plugin Example: SQLitePlugin</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="toctree-wrapper compound">
+</div>
+</div>
+<div class="section" id="license">
+<h2>License<a class="headerlink" href="#license" title="Permalink to this headline">¶</a></h2>
+<p>Code and documentation are available according to the MIT License:</p>
+<div class="highlight-python"><pre>Copyright (c) 2012, Marcel Hellkamp.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+</pre>
+</div>
+<p>The Bottle logo however is <em>NOT</em> covered by that license. It is allowed to
+use the logo as a link to the bottle homepage or in direct context with
+the unmodified library. In all other cases please ask first.</p>
+<p class="rubric">Footnotes</p>
+<table class="docutils footnote" frame="void" id="id3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2">[1]</a></td><td>Usage of the template or server adapter classes of course requires the corresponding template or server modules.</td></tr>
+</tbody>
+</table>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="#">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p><p>
+   Bottle is a fast, simple and lightweight WSGI micro web-framework for Python.
+</p>
+<h3>Some Links</h3>
+<ul>
+  <li><a target="_blank" href="https://github.com/defnull/bottle/issues">Issue Tracker</a></li>
+  <li><a target="_blank" href="http://blog.bottlepy.org">Development Blog</a></li>
+  <li><a target="_blank" href="http://pypi.python.org/pypi/bottle">Bottle @ PyPI</a></li>
+  <li><a target="_blank" href="https://github.com/defnull/bottle">Bottle @ GitHub</a></li>
+  <li><a target="_blank" href="http://groups.google.de/group/bottlepy">Bottle @ Google Groups</a></li>
+  <li><a target="_blank" href="http://twitter.com/bottlepy">Bottle @ Twitter</a></li>
+  <li><a target="_blank" href="http://webchat.freenode.net/?channels=bottlepy">Bottle @ Freenode (Chat)</a></li>
+</ul>
+<h3>Installation</h3>
+<p>Install Bottle with <code>pip&nbsp;install&nbsp;bottle</code> or download the source package at <a href="http://pypi.python.org/pypi/bottle">PyPI</a>.</p>
+<h3>Documentation</h3>
+<p>
+  Download this documentation as <a href="bottle-docs.pdf">PDF</a> or <a href="bottle-docs.zip">HTML (zip)</a> for offline use.
+</p>
+<h3>Sources</h3>
+<p>Browse the sources at <a href="https://github.com/defnull/bottle">GitHub</a>.</p>
+<h3>Other Releases</h3>
+<ul>
+  
+    
+      <li><a href="/docs/dev/">Bottle dev</a> (development)</li>
+  
+  
+    
+      <li><a href="/docs/0.11/">Bottle 0.11</a> (stable)</li>
+  
+  
+    
+      <li><a href="/docs/0.10/">Bottle 0.10</a> (old stable)</li>
+  
+  
+</ul>
+
+
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/index.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="tutorial.html" title="Tutorial"
+             >next</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="#">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_index';
+      var disqus_title = 'Bottle: Python Web Framework';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="##license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/objects.inv b/html/objects.inv
new file mode 100644 (file)
index 0000000..9b53aed
Binary files /dev/null and b/html/objects.inv differ
diff --git a/html/plugindev.html b/html/plugindev.html
new file mode 100644 (file)
index 0000000..27f9389
--- /dev/null
@@ -0,0 +1,439 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Plugin Development Guide &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="List of available Plugins" href="plugins/index.html" />
+    <link rel="prev" title="Developer Notes" href="development.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="plugins/index.html" title="List of available Plugins"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="development.html" title="Developer Notes"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <span class="target" id="module-bottle"></span><div class="section" id="plugin-development-guide">
+<h1>Plugin Development Guide<a class="headerlink" href="#plugin-development-guide" title="Permalink to this headline">¶</a></h1>
+<p>This guide explains the plugin API and how to write custom plugins. I suggest reading <a class="reference internal" href="tutorial.html#plugins"><em>Plugins</em></a> first if you have not done that already. You might also want to have a look at the <a class="reference internal" href="plugins/index.html"><em>List of available Plugins</em></a> for some practical examples.</p>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">This is a draft. If you see any errors or find that a specific part is not explained clear enough, please tell the <a class="reference external" href="mailto:bottlepy&#37;&#52;&#48;googlegroups&#46;com">mailing-list</a> or file a <a class="reference external" href="https://github.com/defnull/bottle/issues">bug report</a>.</p>
+</div>
+<div class="section" id="how-plugins-work-the-basics">
+<h2>How Plugins Work: The Basics<a class="headerlink" href="#how-plugins-work-the-basics" title="Permalink to this headline">¶</a></h2>
+<p>The plugin API builds on the concept of <a class="reference external" href="http://docs.python.org/glossary.html#term-decorator">decorators</a>. To put it briefly, a plugin is a decorator applied to every single route callback of an application.</p>
+<p>Of course, this is just a simplification. Plugins can do a lot more than just decorating route callbacks, but it is a good starting point. Lets have a look at some code:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">response</span><span class="p">,</span> <span class="n">install</span>
+<span class="kn">import</span> <span class="nn">time</span>
+
+<span class="k">def</span> <span class="nf">stopwatch</span><span class="p">(</span><span class="n">callback</span><span class="p">):</span>
+    <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
+        <span class="n">body</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s">&#39;X-Exec-Time&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span>
+        <span class="k">return</span> <span class="n">body</span>
+    <span class="k">return</span> <span class="n">wrapper</span>
+
+<span class="n">install</span><span class="p">(</span><span class="n">stopwatch</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This plugin measures the execution time for each request and adds an appropriate <tt class="docutils literal"><span class="pre">X-Exec-Time</span></tt> header to the response. As you can see, the plugin returns a wrapper and the wrapper calls the original callback recursively. This is how decorators usually work.</p>
+<p>The last line tells Bottle to install the plugin to the default application. This causes the plugin to be automatically applied to all routes of that application. In other words, <tt class="docutils literal"><span class="pre">stopwatch()</span></tt> is called once for each route callback and the return value is used as a replacement for the original callback.</p>
+<p>Plugins are applied on demand, that is, as soon as a route is requested for the first time. For this to work properly in multi-threaded environments, the plugin should be thread-safe. This is not a problem most of the time, but keep it in mind.</p>
+<p>Once all plugins are applied to a route, the wrapped callback is cached and subsequent requests are handled by the cached version directly. This means that a plugin is usually applied only once to a specific route. That cache, however, is cleared every time the list of installed plugins changes. Your plugin should be able to decorate the same route more than once.</p>
+<p>The decorator API is quite limited, though. You don&#8217;t know anything about the route being decorated or the associated application object and have no way to efficiently store data that is shared among all routes. But fear not! Plugins are not limited to just decorator functions. Bottle accepts anything as a plugin as long as it is callable or implements an extended API. This API is described below and gives you a lot of control over the whole process.</p>
+</div>
+<div class="section" id="plugin-api">
+<h2>Plugin API<a class="headerlink" href="#plugin-api" title="Permalink to this headline">¶</a></h2>
+<p><a class="reference internal" href="#bottle.Plugin" title="bottle.Plugin"><tt class="xref py py-class docutils literal"><span class="pre">Plugin</span></tt></a> is not a real class (you cannot import it from <a class="reference internal" href="tutorial.html#module-bottle" title="bottle"><tt class="xref py py-mod docutils literal"><span class="pre">bottle</span></tt></a>) but an interface that plugins are expected to implement. Bottle accepts any object of any type as a plugin, as long as it conforms to the following API.</p>
+<dl class="class">
+<dt id="bottle.Plugin">
+<em class="property">class </em><tt class="descname">Plugin</tt><big>(</big><em>object</em><big>)</big><a class="headerlink" href="#bottle.Plugin" title="Permalink to this definition">¶</a></dt>
+<dd><p>Plugins must be callable or implement <a class="reference internal" href="#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">apply()</span></tt></a>. If <a class="reference internal" href="#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">apply()</span></tt></a> is defined, it is always preferred over calling the plugin directly. All other methods and attributes are optional.</p>
+<dl class="attribute">
+<dt id="bottle.Plugin.name">
+<tt class="descname">name</tt><a class="headerlink" href="#bottle.Plugin.name" title="Permalink to this definition">¶</a></dt>
+<dd><p>Both <a class="reference internal" href="api.html#bottle.Bottle.uninstall" title="bottle.Bottle.uninstall"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.uninstall()</span></tt></a> and the <cite>skip</cite> parameter of <a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a> accept a name string to refer to a plugin or plugin type. This works only for plugins that have a name attribute.</p>
+</dd></dl>
+
+<dl class="attribute">
+<dt id="bottle.Plugin.api">
+<tt class="descname">api</tt><a class="headerlink" href="#bottle.Plugin.api" title="Permalink to this definition">¶</a></dt>
+<dd><p>The Plugin API is still evolving. This integer attribute tells bottle which version to use. If it is missing, bottle defaults to the first version. The current version is <tt class="docutils literal"><span class="pre">2</span></tt>. See <a class="reference internal" href="#plugin-changelog"><em>Plugin API changes</em></a> for details.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Plugin.setup">
+<tt class="descname">setup</tt><big>(</big><em>self</em>, <em>app</em><big>)</big><a class="headerlink" href="#bottle.Plugin.setup" title="Permalink to this definition">¶</a></dt>
+<dd><p>Called as soon as the plugin is installed to an application (see <a class="reference internal" href="api.html#bottle.Bottle.install" title="bottle.Bottle.install"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.install()</span></tt></a>). The only parameter is the associated application object.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Plugin.__call__">
+<tt class="descname">__call__</tt><big>(</big><em>self</em>, <em>callback</em><big>)</big><a class="headerlink" href="#bottle.Plugin.__call__" title="Permalink to this definition">¶</a></dt>
+<dd><p>As long as <a class="reference internal" href="#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">apply()</span></tt></a> is not defined, the plugin itself is used as a decorator and applied directly to each route callback. The only parameter is the callback to decorate. Whatever is returned by this method replaces the original callback. If there is no need to wrap or replace a given callback, just return the unmodified callback parameter.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Plugin.apply">
+<tt class="descname">apply</tt><big>(</big><em>self</em>, <em>callback</em>, <em>route</em><big>)</big><a class="headerlink" href="#bottle.Plugin.apply" title="Permalink to this definition">¶</a></dt>
+<dd><p>If defined, this method is used in favor of <a class="reference internal" href="#bottle.Plugin.__call__" title="bottle.Plugin.__call__"><tt class="xref py py-meth docutils literal"><span class="pre">__call__()</span></tt></a> to decorate route callbacks. The additional <cite>route</cite> parameter is an instance of <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> and provides a lot of meta-information and context for that route. See <a class="reference internal" href="#route-context"><em>The Route Context</em></a> for details.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.Plugin.close">
+<tt class="descname">close</tt><big>(</big><em>self</em><big>)</big><a class="headerlink" href="#bottle.Plugin.close" title="Permalink to this definition">¶</a></dt>
+<dd><p>Called immediately before the plugin is uninstalled or the application is closed (see <a class="reference internal" href="api.html#bottle.Bottle.uninstall" title="bottle.Bottle.uninstall"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.uninstall()</span></tt></a> or <a class="reference internal" href="api.html#bottle.Bottle.close" title="bottle.Bottle.close"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.close()</span></tt></a>).</p>
+</dd></dl>
+
+</dd></dl>
+
+<p>Both <a class="reference internal" href="#bottle.Plugin.setup" title="bottle.Plugin.setup"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.setup()</span></tt></a> and <a class="reference internal" href="#bottle.Plugin.close" title="bottle.Plugin.close"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.close()</span></tt></a> are <em>not</em> called for plugins that are applied directly to a route via the <a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a> decorator, but only for plugins installed to an application.</p>
+<div class="section" id="plugin-api-changes">
+<span id="plugin-changelog"></span><h3>Plugin API changes<a class="headerlink" href="#plugin-api-changes" title="Permalink to this headline">¶</a></h3>
+<p>The Plugin API is still evolving and changed with Bottle 0.10 to address certain issues with the route context dictionary. To ensure backwards compatibility with 0.9 Plugins, we added an optional <a class="reference internal" href="#bottle.Plugin.api" title="bottle.Plugin.api"><tt class="xref py py-attr docutils literal"><span class="pre">Plugin.api</span></tt></a> attribute to tell bottle which API to use. The API differences are summarized here.</p>
+<ul class="simple">
+<li><strong>Bottle 0.9 API 1</strong> (<a class="reference internal" href="#bottle.Plugin.api" title="bottle.Plugin.api"><tt class="xref py py-attr docutils literal"><span class="pre">Plugin.api</span></tt></a> not present)<ul>
+<li>Original Plugin API as described in the 0.9 docs.</li>
+</ul>
+</li>
+<li><strong>Bottle 0.10 API 2</strong> (<a class="reference internal" href="#bottle.Plugin.api" title="bottle.Plugin.api"><tt class="xref py py-attr docutils literal"><span class="pre">Plugin.api</span></tt></a> equals 2)<ul>
+<li>The <cite>context</cite> parameter of the <a class="reference internal" href="#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.apply()</span></tt></a> method is now an instance of <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> instead of a context dictionary.</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div class="section" id="the-route-context">
+<span id="route-context"></span><h2>The Route Context<a class="headerlink" href="#the-route-context" title="Permalink to this headline">¶</a></h2>
+<p>The <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> instance passed to <a class="reference internal" href="#bottle.Plugin.apply" title="bottle.Plugin.apply"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.apply()</span></tt></a> provides detailed informations about the associated route. The most important attributes are summarized here:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="14%" />
+<col width="86%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Attribute</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>app</td>
+<td>The application object this route is installed to.</td>
+</tr>
+<tr class="row-odd"><td>rule</td>
+<td>The rule string (e.g. <tt class="docutils literal"><span class="pre">/wiki/:page</span></tt>).</td>
+</tr>
+<tr class="row-even"><td>method</td>
+<td>The HTTP method as a string (e.g. <tt class="docutils literal"><span class="pre">GET</span></tt>).</td>
+</tr>
+<tr class="row-odd"><td>callback</td>
+<td>The original callback with no plugins applied. Useful for
+introspection.</td>
+</tr>
+<tr class="row-even"><td>name</td>
+<td>The name of the route (if specified) or <tt class="docutils literal"><span class="pre">None</span></tt>.</td>
+</tr>
+<tr class="row-odd"><td>plugins</td>
+<td>A list of route-specific plugins. These are applied in addition to
+application-wide plugins. (see <a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a>).</td>
+</tr>
+<tr class="row-even"><td>skiplist</td>
+<td>A list of plugins to not apply to this route (again, see
+<a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a>).</td>
+</tr>
+<tr class="row-odd"><td>config</td>
+<td>Additional keyword arguments passed to the <a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a>
+decorator are stored in this dictionary. Used for route-specific
+configuration and meta-data.</td>
+</tr>
+</tbody>
+</table>
+<p>For your plugin, <a class="reference internal" href="api.html#bottle.Route.config" title="bottle.Route.config"><tt class="xref py py-attr docutils literal"><span class="pre">Route.config</span></tt></a> is probably the most important attribute. Keep in mind that this dictionary is local to the route, but shared between all plugins. It is always a good idea to add a unique prefix or, if your plugin needs a lot of configuration, store it in a separate namespace within the <cite>config</cite> dictionary. This helps to avoid naming collisions between plugins.</p>
+<div class="section" id="changing-the-route-object">
+<h3>Changing the <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> object<a class="headerlink" href="#changing-the-route-object" title="Permalink to this headline">¶</a></h3>
+<p>While some <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> attributes are mutable, changes may have unwanted effects on other plugins. It is most likely a bad idea to monkey-patch a broken route instead of providing a helpful error message and let the user fix the problem.</p>
+<p>In some rare cases, however, it might be justifiable to break this rule. After you made your changes to the <a class="reference internal" href="api.html#bottle.Route" title="bottle.Route"><tt class="xref py py-class docutils literal"><span class="pre">Route</span></tt></a> instance, raise <tt class="xref py py-exc docutils literal"><span class="pre">RouteReset</span></tt> as an exception. This removes the current route from the cache and causes all plugins to be re-applied. The router is not updated, however. Changes to <cite>rule</cite> or <cite>method</cite> values have no effect on the router, but only on plugins. This may change in the future, though.</p>
+</div>
+</div>
+<div class="section" id="runtime-optimizations">
+<h2>Runtime optimizations<a class="headerlink" href="#runtime-optimizations" title="Permalink to this headline">¶</a></h2>
+<p>Once all plugins are applied to a route, the wrapped route callback is cached to speed up subsequent requests. If the behavior of your plugin depends on configuration, and you want to be able to change that configuration at runtime, you need to read the configuration on each request. Easy enough.</p>
+<p>For performance reasons, however, it might be worthwhile to choose a different wrapper based on current needs, work with closures, or enable or disable a plugin at runtime. Let&#8217;s take the built-in HooksPlugin as an example: If no hooks are installed, the plugin removes itself from all affected routes and has virtaully no overhead. As soon as you install the first hook, the plugin activates itself and takes effect again.</p>
+<p>To achieve this, you need control over the callback cache: <a class="reference internal" href="api.html#bottle.Route.reset" title="bottle.Route.reset"><tt class="xref py py-meth docutils literal"><span class="pre">Route.reset()</span></tt></a> clears the cache for a single route and <a class="reference internal" href="api.html#bottle.Bottle.reset" title="bottle.Bottle.reset"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.reset()</span></tt></a> clears all caches for all routes of an application at once. On the next request, all plugins are re-applied to the route as if it were requested for the first time.</p>
+<p>Both methods won&#8217;t affect the current request if called from within a route callback, of cause. To force a restart of the current request, raise <tt class="xref py py-exc docutils literal"><span class="pre">RouteReset</span></tt> as an exception.</p>
+</div>
+<div class="section" id="plugin-example-sqliteplugin">
+<h2>Plugin Example: SQLitePlugin<a class="headerlink" href="#plugin-example-sqliteplugin" title="Permalink to this headline">¶</a></h2>
+<p>This plugin provides an sqlite3 database connection handle as an additional keyword argument to wrapped callbacks, but only if the callback expects it. If not, the route is ignored and no overhead is added. The wrapper does not affect the return value, but handles plugin-related exceptions properly. <a class="reference internal" href="#bottle.Plugin.setup" title="bottle.Plugin.setup"><tt class="xref py py-meth docutils literal"><span class="pre">Plugin.setup()</span></tt></a> is used to inspect the application and search for conflicting plugins.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sqlite3</span>
+<span class="kn">import</span> <span class="nn">inspect</span>
+
+<span class="k">class</span> <span class="nc">SQLitePlugin</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; This plugin passes an sqlite3 database handle to route callbacks</span>
+<span class="sd">    that accept a `db` keyword argument. If a callback does not expect</span>
+<span class="sd">    such a parameter, no connection is made. You can override the database</span>
+<span class="sd">    settings on a per-route basis. &#39;&#39;&#39;</span>
+
+    <span class="n">name</span> <span class="o">=</span> <span class="s">&#39;sqlite&#39;</span>
+    <span class="n">api</span> <span class="o">=</span> <span class="mi">2</span>
+
+    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;:memory:&#39;</span><span class="p">,</span> <span class="n">autocommit</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">dictrows</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
+                 <span class="n">keyword</span><span class="o">=</span><span class="s">&#39;db&#39;</span><span class="p">):</span>
+         <span class="bp">self</span><span class="o">.</span><span class="n">dbfile</span> <span class="o">=</span> <span class="n">dbfile</span>
+         <span class="bp">self</span><span class="o">.</span><span class="n">autocommit</span> <span class="o">=</span> <span class="n">autocommit</span>
+         <span class="bp">self</span><span class="o">.</span><span class="n">dictrows</span> <span class="o">=</span> <span class="n">dictrows</span>
+         <span class="bp">self</span><span class="o">.</span><span class="n">keyword</span> <span class="o">=</span> <span class="n">keyword</span>
+
+    <span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
+        <span class="sd">&#39;&#39;&#39; Make sure that other installed plugins don&#39;t affect the same</span>
+<span class="sd">            keyword argument.&#39;&#39;&#39;</span>
+        <span class="k">for</span> <span class="n">other</span> <span class="ow">in</span> <span class="n">app</span><span class="o">.</span><span class="n">plugins</span><span class="p">:</span>
+            <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">other</span><span class="p">,</span> <span class="n">SQLitePlugin</span><span class="p">):</span> <span class="k">continue</span>
+            <span class="k">if</span> <span class="n">other</span><span class="o">.</span><span class="n">keyword</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyword</span><span class="p">:</span>
+                <span class="k">raise</span> <span class="n">PluginError</span><span class="p">(</span><span class="s">&quot;Found another sqlite plugin with &quot;</span>\
+                <span class="s">&quot;conflicting settings (non-unique keyword).&quot;</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">apply</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
+        <span class="c"># Override global configuration with route-specific values.</span>
+        <span class="n">conf</span> <span class="o">=</span> <span class="n">context</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;sqlite&#39;</span><span class="p">)</span> <span class="ow">or</span> <span class="p">{}</span>
+        <span class="n">dbfile</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;dbfile&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dbfile</span><span class="p">)</span>
+        <span class="n">autocommit</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;autocommit&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">autocommit</span><span class="p">)</span>
+        <span class="n">dictrows</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;dictrows&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">dictrows</span><span class="p">)</span>
+        <span class="n">keyword</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;keyword&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">keyword</span><span class="p">)</span>
+
+        <span class="c"># Test if the original callback accepts a &#39;db&#39; keyword.</span>
+        <span class="c"># Ignore it if it does not need a database handle.</span>
+        <span class="n">args</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getargspec</span><span class="p">(</span><span class="n">context</span><span class="o">.</span><span class="n">callback</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
+        <span class="k">if</span> <span class="n">keyword</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
+            <span class="k">return</span> <span class="n">callback</span>
+
+        <span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
+            <span class="c"># Connect to the database</span>
+            <span class="n">db</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">dbfile</span><span class="p">)</span>
+            <span class="c"># This enables column access by name: row[&#39;column_name&#39;]</span>
+            <span class="k">if</span> <span class="n">dictrows</span><span class="p">:</span> <span class="n">db</span><span class="o">.</span><span class="n">row_factory</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">Row</span>
+            <span class="c"># Add the connection handle as a keyword argument.</span>
+            <span class="n">kwargs</span><span class="p">[</span><span class="n">keyword</span><span class="p">]</span> <span class="o">=</span> <span class="n">db</span>
+
+            <span class="k">try</span><span class="p">:</span>
+                <span class="n">rv</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
+                <span class="k">if</span> <span class="n">autocommit</span><span class="p">:</span> <span class="n">db</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+            <span class="k">except</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">IntegrityError</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
+                <span class="n">db</span><span class="o">.</span><span class="n">rollback</span><span class="p">()</span>
+                <span class="k">raise</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s">&quot;Database Error&quot;</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span>
+            <span class="k">finally</span><span class="p">:</span>
+                <span class="n">db</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+            <span class="k">return</span> <span class="n">rv</span>
+
+        <span class="c"># Replace the route callback with the wrapped one.</span>
+        <span class="k">return</span> <span class="n">wrapper</span>
+</pre></div>
+</div>
+<p>This plugin is actually useful and very similar to the version bundled with Bottle. Not bad for less than 60 lines of code, don&#8217;t you think? Here is a usage example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">sqlite</span> <span class="o">=</span> <span class="n">SQLitePlugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">)</span>
+<span class="n">bottle</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">sqlite</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/show/:page&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">page</span><span class="p">,</span> <span class="n">db</span><span class="p">):</span>
+    <span class="n">row</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;SELECT * from pages where name=?&#39;</span><span class="p">,</span> <span class="n">page</span><span class="p">)</span><span class="o">.</span><span class="n">fetchone</span><span class="p">()</span>
+    <span class="k">if</span> <span class="n">row</span><span class="p">:</span>
+        <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;showpage&#39;</span><span class="p">,</span> <span class="n">page</span><span class="o">=</span><span class="n">row</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="s">&quot;Page not found&quot;</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/static/:fname#.*#&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">static</span><span class="p">(</span><span class="n">fname</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">fname</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/some/path&#39;</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/admin/set/:db#[a-zA-Z]+#&#39;</span><span class="p">,</span> <span class="n">skip</span><span class="o">=</span><span class="p">[</span><span class="n">sqlite</span><span class="p">])</span>
+<span class="k">def</span> <span class="nf">change_dbfile</span><span class="p">(</span><span class="n">db</span><span class="p">):</span>
+    <span class="n">sqlite</span><span class="o">.</span><span class="n">dbfile</span> <span class="o">=</span> <span class="s">&#39;/tmp/</span><span class="si">%s</span><span class="s">.db&#39;</span> <span class="o">%</span> <span class="n">db</span>
+    <span class="k">return</span> <span class="s">&quot;Switched DB to </span><span class="si">%s</span><span class="s">.db&quot;</span> <span class="o">%</span> <span class="n">db</span>
+</pre></div>
+</div>
+<p>The first route needs a database connection and tells the plugin to create a handle by requesting a <tt class="docutils literal"><span class="pre">db</span></tt> keyword argument. The second route does not need a database and is therefore ignored by the plugin. The third route does expect a &#8216;db&#8217; keyword argument, but explicitly skips the sqlite plugin. This way the argument is not overruled by the plugin and still contains the value of the same-named url argument.</p>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Plugin Development Guide</a><ul>
+<li><a class="reference internal" href="#how-plugins-work-the-basics">How Plugins Work: The Basics</a></li>
+<li><a class="reference internal" href="#plugin-api">Plugin API</a><ul>
+<li><a class="reference internal" href="#plugin-api-changes">Plugin API changes</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#the-route-context">The Route Context</a><ul>
+<li><a class="reference internal" href="#changing-the-route-object">Changing the <tt class="docutils literal"><span class="pre">Route</span></tt> object</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#runtime-optimizations">Runtime optimizations</a></li>
+<li><a class="reference internal" href="#plugin-example-sqliteplugin">Plugin Example: SQLitePlugin</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="development.html"
+                        title="previous chapter">Developer Notes</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="plugins/index.html"
+                        title="next chapter">List of available Plugins</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/plugindev.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="plugins/index.html" title="List of available Plugins"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="development.html" title="Developer Notes"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_plugindev';
+      var disqus_title = 'Plugin Development Guide';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/plugins/index.html b/html/plugins/index.html
new file mode 100644 (file)
index 0000000..98a5d36
--- /dev/null
@@ -0,0 +1,216 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>List of available Plugins &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="../_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '../',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="../_static/jquery.js"></script>
+    <script type="text/javascript" src="../_static/underscore.js"></script>
+    <script type="text/javascript" src="../_static/doctools.js"></script>
+    <link rel="shortcut icon" href="../_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="../index.html" />
+    <link rel="next" title="Bottle-SQLite" href="sqlite.html" />
+    <link rel="prev" title="Plugin Development Guide" href="../plugindev.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="../_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="../_static/logo_reddit.png" />
+    <script type="application/javascript" src="../_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="sqlite.html" title="Bottle-SQLite"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="../plugindev.html" title="Plugin Development Guide"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <span class="target" id="module-bottle"></span><div class="section" id="list-of-available-plugins">
+<h1>List of available Plugins<a class="headerlink" href="#list-of-available-plugins" title="Permalink to this headline">¶</a></h1>
+<p>This is a list of third-party plugins that add extend Bottles core functionality or integrate other libraries with the Bottle framework.</p>
+<p>Have a look at <a class="reference internal" href="../tutorial.html#plugins"><em>Plugins</em></a> for general questions about plugins (installation, usage). If you plan to develop a new plugin, the <a class="reference internal" href="../plugindev.html"><em>Plugin Development Guide</em></a> may help you.</p>
+<dl class="docutils">
+<dt><a class="reference external" href="http://cork.firelet.net/">Bottle-Cork</a></dt>
+<dd>Cork provides a simple set of methods to implement Authentication and Authorization in web applications based on Bottle.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-extras/">Bottle-Extras</a></dt>
+<dd>Meta package to install the bottle plugin collection.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-flash/">Bottle-Flash</a></dt>
+<dd>flash plugin for bottle</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-hotqueue/">Bottle-Hotqueue</a></dt>
+<dd>FIFO Queue for Bottle built upon redis</dd>
+<dt><a class="reference external" href="http://nobrin.github.com/macaron/webapp.html">Macaron</a></dt>
+<dd>Macaron is an object-relational mapper (ORM) for SQLite.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-memcache/">Bottle-Memcache</a></dt>
+<dd>Memcache integration for Bottle.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-mongodb/">Bottle-MongoDB</a></dt>
+<dd>MongoDB integration for Bottle</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-redis/">Bottle-Redis</a></dt>
+<dd>Redis integration for Bottle.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-renderer/">Bottle-Renderer</a></dt>
+<dd>Renderer plugin for bottle</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-servefiles/">Bottle-Servefiles</a></dt>
+<dd>A reusable app that serves static files for bottle apps</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-sqlalchemy/">Bottle-Sqlalchemy</a></dt>
+<dd>SQLAlchemy integration for Bottle.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-sqlite/">Bottle-Sqlite</a></dt>
+<dd>SQLite3 database integration for Bottle.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-web2pydal/">Bottle-Web2pydal</a></dt>
+<dd>Web2py Dal integration for Bottle.</dd>
+<dt><a class="reference external" href="http://pypi.python.org/pypi/bottle-werkzeug/">Bottle-Werkzeug</a></dt>
+<dd>Integrates the <cite>werkzeug</cite> library (alternative request and response objects, advanced debugging middleware and more).</dd>
+</dl>
+<p>Plugins listed here are not part of Bottle or the Bottle project, but developed and maintained by third parties.</p>
+<div class="toctree-wrapper compound">
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="../index.html">
+              <img class="logo" src="../_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="../plugindev.html"
+                        title="previous chapter">Plugin Development Guide</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="sqlite.html"
+                        title="next chapter">Bottle-SQLite</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/index.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="../_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="../search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="sqlite.html" title="Bottle-SQLite"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="../plugindev.html" title="Plugin Development Guide"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_plugins/index';
+      var disqus_title = 'List of available Plugins';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="../index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="../contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/plugins/sqlite.html b/html/plugins/sqlite.html
new file mode 100644 (file)
index 0000000..d6e26e0
--- /dev/null
@@ -0,0 +1,272 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Bottle-SQLite &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="../_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '../',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="../_static/jquery.js"></script>
+    <script type="text/javascript" src="../_static/underscore.js"></script>
+    <script type="text/javascript" src="../_static/doctools.js"></script>
+    <link rel="shortcut icon" href="../_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="../index.html" />
+    <link rel="up" title="List of available Plugins" href="index.html" />
+    <link rel="next" title="Bottle-Werkzeug" href="werkzeug.html" />
+    <link rel="prev" title="List of available Plugins" href="index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="../_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="../_static/logo_reddit.png" />
+    <script type="application/javascript" src="../_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="werkzeug.html" title="Bottle-Werkzeug"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="index.html" title="List of available Plugins"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+
+          <li><a href="index.html" accesskey="U">List of available Plugins</a> &raquo;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="bottle-sqlite">
+<h1>Bottle-SQLite<a class="headerlink" href="#bottle-sqlite" title="Permalink to this headline">¶</a></h1>
+<p>SQLite is a self-contained SQL database engine that runs locally and does not
+require any additional server software or setup. The sqlite3 module is part of the
+Python standard library and already installed on most systems. It it very useful
+for prototyping database-driven applications that are later ported to larger
+databases such as PostgreSQL or MySQL.</p>
+<p>This plugin simplifies the use of sqlite databases in your Bottle applications.
+Once installed, all you have to do is to add a <tt class="docutils literal"><span class="pre">db</span></tt> keyword argument
+(configurable) to route callbacks that need a database connection.</p>
+<div class="section" id="installation">
+<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
+<p>Install with one of the following commands:</p>
+<div class="highlight-python"><pre>$ pip install bottle-sqlite
+$ easy_install bottle-sqlite</pre>
+</div>
+<p>or download the latest version from github:</p>
+<div class="highlight-python"><pre>$ git clone git://github.com/defnull/bottle.git
+$ cd bottle/plugins/sqlite
+$ python setup.py install</pre>
+</div>
+</div>
+<div class="section" id="usage">
+<h2>Usage<a class="headerlink" href="#usage" title="Permalink to this headline">¶</a></h2>
+<p>Once installed to an application, the plugin passes an open
+<a class="reference external" href="http://docs.python.org/library/sqlite3.html#sqlite3.Connection" title="(in Python v2.7)"><tt class="xref py py-class docutils literal"><span class="pre">sqlite3.Connection</span></tt></a> instance to all routes that require a <tt class="docutils literal"><span class="pre">db</span></tt> keyword
+argument:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">bottle</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">Bottle</span><span class="p">()</span>
+<span class="n">plugin</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">ext</span><span class="o">.</span><span class="n">sqlite</span><span class="o">.</span><span class="n">Plugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">)</span>
+<span class="n">app</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">plugin</span><span class="p">)</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/show/:item&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">db</span><span class="p">):</span>
+    <span class="n">row</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;SELECT * from items where name=?&#39;</span><span class="p">,</span> <span class="n">item</span><span class="p">)</span><span class="o">.</span><span class="n">fetchone</span><span class="p">()</span>
+    <span class="k">if</span> <span class="n">row</span><span class="p">:</span>
+        <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;showitem&#39;</span><span class="p">,</span> <span class="n">page</span><span class="o">=</span><span class="n">row</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">HTTPError</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="s">&quot;Page not found&quot;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Routes that do not expect a <tt class="docutils literal"><span class="pre">db</span></tt> keyword argument are not affected.</p>
+<p>The connection handle is configured so that <a class="reference external" href="http://docs.python.org/library/sqlite3.html#sqlite3.Row" title="(in Python v2.7)"><tt class="xref py py-class docutils literal"><span class="pre">sqlite3.Row</span></tt></a> objects can be
+accessed both by index (like tuples) and case-insensitively by name. At the end of
+the request cycle, outstanding transactions are committed and the connection is
+closed automatically. If an error occurs, any changes to the database since the
+last commit are rolled back to keep the database in a consistent state.</p>
+</div>
+<div class="section" id="configuration">
+<h2>Configuration<a class="headerlink" href="#configuration" title="Permalink to this headline">¶</a></h2>
+<p>The following configuration options exist for the plugin class:</p>
+<ul class="simple">
+<li><strong>dbfile</strong>: Database filename (default: in-memory database).</li>
+<li><strong>keyword</strong>: The keyword argument name that triggers the plugin (default: &#8216;db&#8217;).</li>
+<li><strong>autocommit</strong>: Whether or not to commit outstanding transactions at the end of the request cycle (default: True).</li>
+<li><strong>dictrows</strong>: Whether or not to support dict-like access to row objects (default: True).</li>
+</ul>
+<p>You can override each of these values on a per-route basis:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/cache/:item&#39;</span><span class="p">,</span> <span class="n">sqlite</span><span class="o">=</span><span class="p">{</span><span class="s">&#39;dbfile&#39;</span><span class="p">:</span> <span class="s">&#39;:memory:&#39;</span><span class="p">})</span>
+<span class="k">def</span> <span class="nf">cache</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">db</span><span class="p">):</span>
+    <span class="o">...</span>
+</pre></div>
+</div>
+<p>or install two plugins with different <tt class="docutils literal"><span class="pre">keyword</span></tt> settings to the same application:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">Bottle</span><span class="p">()</span>
+<span class="n">test_db</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">ext</span><span class="o">.</span><span class="n">sqlite</span><span class="o">.</span><span class="n">Plugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">)</span>
+<span class="n">cache_db</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">ext</span><span class="o">.</span><span class="n">sqlite</span><span class="o">.</span><span class="n">Plugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;:memory:&#39;</span><span class="p">,</span> <span class="n">keyword</span><span class="o">=</span><span class="s">&#39;cache&#39;</span><span class="p">)</span>
+<span class="n">app</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">test_db</span><span class="p">)</span>
+<span class="n">app</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">cache_db</span><span class="p">)</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/show/:item&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">db</span><span class="p">):</span>
+    <span class="o">...</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/cache/:item&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">cache</span><span class="p">(</span><span class="n">item</span><span class="p">,</span> <span class="n">cache</span><span class="p">):</span>
+    <span class="o">...</span>
+</pre></div>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="../index.html">
+              <img class="logo" src="../_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="../index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Bottle-SQLite</a><ul>
+<li><a class="reference internal" href="#installation">Installation</a></li>
+<li><a class="reference internal" href="#usage">Usage</a></li>
+<li><a class="reference internal" href="#configuration">Configuration</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="index.html"
+                        title="previous chapter">List of available Plugins</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="werkzeug.html"
+                        title="next chapter">Bottle-Werkzeug</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/sqlite.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="../_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="../search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="werkzeug.html" title="Bottle-Werkzeug"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="index.html" title="List of available Plugins"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+
+          <li><a href="index.html" >List of available Plugins</a> &raquo;</li> 
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_plugins/sqlite';
+      var disqus_title = 'Bottle-SQLite';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="../index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="../contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/plugins/werkzeug.html b/html/plugins/werkzeug.html
new file mode 100644 (file)
index 0000000..2f25c03
--- /dev/null
@@ -0,0 +1,248 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Bottle-Werkzeug &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="../_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '../',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="../_static/jquery.js"></script>
+    <script type="text/javascript" src="../_static/underscore.js"></script>
+    <script type="text/javascript" src="../_static/doctools.js"></script>
+    <link rel="shortcut icon" href="../_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="../index.html" />
+    <link rel="up" title="List of available Plugins" href="index.html" />
+    <link rel="prev" title="Bottle-SQLite" href="sqlite.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="../_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="../_static/logo_reddit.png" />
+    <script type="application/javascript" src="../_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="sqlite.html" title="Bottle-SQLite"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+
+          <li><a href="index.html" accesskey="U">List of available Plugins</a> &raquo;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="bottle-werkzeug">
+<h1>Bottle-Werkzeug<a class="headerlink" href="#bottle-werkzeug" title="Permalink to this headline">¶</a></h1>
+<p><a class="reference external" href="http://werkzeug.pocoo.org/">Werkzeug</a> is a powerful WSGI utility library for
+Python. It includes an interactive debugger and feature-packed request and response
+objects.</p>
+<p>This plugin integrates <a class="reference external" href="http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Request" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.wrappers.Request</span></tt></a> and
+<a class="reference external" href="http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Response" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.wrappers.Response</span></tt></a> as an alternative to the built-in
+implementations, adds support for <a class="reference external" href="http://werkzeug.pocoo.org/docs/exceptions/#werkzeug.exceptions" title="(in Werkzeug v0.9)"><tt class="xref py py-mod docutils literal"><span class="pre">werkzeug.exceptions</span></tt></a> and replaces the
+default error page with an interactive debugger.</p>
+<div class="section" id="installation">
+<h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
+<p>Install with one of the following commands:</p>
+<div class="highlight-python"><pre>$ pip install bottle-werkzeug
+$ easy_install bottle-werkzeug</pre>
+</div>
+<p>or download the latest version from github:</p>
+<div class="highlight-python"><pre>$ git clone git://github.com/defnull/bottle.git
+$ cd bottle/plugins/werkzeug
+$ python setup.py install</pre>
+</div>
+</div>
+<div class="section" id="usage">
+<h2>Usage<a class="headerlink" href="#usage" title="Permalink to this headline">¶</a></h2>
+<p>Once installed to an application, this plugin adds support for
+<a class="reference external" href="http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Response" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.wrappers.Response</span></tt></a>, all kinds of <a class="reference external" href="http://werkzeug.pocoo.org/docs/exceptions/#werkzeug.exceptions" title="(in Werkzeug v0.9)"><tt class="xref py py-mod docutils literal"><span class="pre">werkzeug.exceptions</span></tt></a> and
+provides a thread-local instance of <a class="reference external" href="http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Request" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.wrappers.Request</span></tt></a> that is
+updated with each request. The plugin instance itself doubles as a werkzeug
+module object, so you don&#8217;t have to import werkzeug in your application. Here
+is an example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">bottle</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">Bottle</span><span class="p">()</span>
+<span class="n">werkzeug</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">ext</span><span class="o">.</span><span class="n">werkzeug</span><span class="o">.</span><span class="n">Plugin</span><span class="p">()</span>
+<span class="n">app</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">werkzeug</span><span class="p">)</span>
+
+<span class="n">req</span> <span class="o">=</span> <span class="n">werkzueg</span><span class="o">.</span><span class="n">request</span> <span class="c"># For the lazy.</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/hello/:name&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">say_hello</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
+    <span class="n">greet</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;en&#39;</span><span class="p">:</span><span class="s">&#39;Hello&#39;</span><span class="p">,</span> <span class="s">&#39;de&#39;</span><span class="p">:</span><span class="s">&#39;Hallo&#39;</span><span class="p">,</span> <span class="s">&#39;fr&#39;</span><span class="p">:</span><span class="s">&#39;Bonjour&#39;</span><span class="p">}</span>
+    <span class="n">language</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="n">accept_languages</span><span class="o">.</span><span class="n">best_match</span><span class="p">(</span><span class="n">greet</span><span class="o">.</span><span class="n">keys</span><span class="p">())</span>
+    <span class="k">if</span> <span class="n">language</span><span class="p">:</span>
+        <span class="k">return</span> <span class="n">werkzeug</span><span class="o">.</span><span class="n">Response</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">!&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">greet</span><span class="p">[</span><span class="n">language</span><span class="p">],</span> <span class="n">name</span><span class="p">))</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">raise</span> <span class="n">werkzeug</span><span class="o">.</span><span class="n">exceptions</span><span class="o">.</span><span class="n">NotAcceptable</span><span class="p">()</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="using-the-debugger">
+<h2>Using the Debugger<a class="headerlink" href="#using-the-debugger" title="Permalink to this headline">¶</a></h2>
+<p>This plugin replaces the default error page with an advanced debugger. If you
+have the <cite>evalex</cite> feature enabled, you will get an interactive console that
+allows you to inspect the error context in the browser. Please read
+<a class="reference external" href="werkzeug:debug">Debugging Applications with werkzeug</a> before you enable this
+feature.</p>
+</div>
+<div class="section" id="configuration">
+<h2>Configuration<a class="headerlink" href="#configuration" title="Permalink to this headline">¶</a></h2>
+<p>The following configuration options exist for the plugin class:</p>
+<ul class="simple">
+<li><strong>evalex</strong>: Enable the exception evaluation feature (interactive debugging). This requires a non-forking server and is a security risk. Please read <a class="reference external" href="werkzeug:debug">Debugging Applications with werkzeug</a>. (default: False)</li>
+<li><strong>request_class</strong>: Defaults to <a class="reference external" href="http://werkzeug.pocoo.org/docs/wrappers/#werkzeug.wrappers.Request" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.wrappers.Request</span></tt></a></li>
+<li><strong>debugger_class</strong>: Defaults to a subclass of <a class="reference external" href="http://werkzeug.pocoo.org/docs/debug/#werkzeug.debug.DebuggedApplication" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.debug.DebuggedApplication</span></tt></a> which obeys the <tt class="xref py py-data docutils literal"><span class="pre">bottle.DEBUG</span></tt> setting.</li>
+</ul>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="../index.html">
+              <img class="logo" src="../_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="../index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Bottle-Werkzeug</a><ul>
+<li><a class="reference internal" href="#installation">Installation</a></li>
+<li><a class="reference internal" href="#usage">Usage</a></li>
+<li><a class="reference internal" href="#using-the-debugger">Using the Debugger</a></li>
+<li><a class="reference internal" href="#configuration">Configuration</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="sqlite.html"
+                        title="previous chapter">Bottle-SQLite</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/werkzeug.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="../_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="../search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="../genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="../py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="sqlite.html" title="Bottle-SQLite"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="../index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+
+          <li><a href="index.html" >List of available Plugins</a> &raquo;</li> 
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_plugins/werkzeug';
+      var disqus_title = 'Bottle-Werkzeug';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="../index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="../contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/py-modindex.html b/html/py-modindex.html
new file mode 100644 (file)
index 0000000..c643af9
--- /dev/null
@@ -0,0 +1,172 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Python Module Index &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+
+    <script type="text/javascript">
+      DOCUMENTATION_OPTIONS.COLLAPSE_INDEX = true;
+    </script>
+
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="#" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+
+   <h1>Python Module Index</h1>
+
+   <div class="modindex-jumpbox">
+   <a href="#cap-b"><strong>b</strong></a>
+   </div>
+
+   <table class="indextable modindextable" cellspacing="0" cellpadding="2">
+     <tr class="pcap"><td></td><td>&nbsp;</td><td></td></tr>
+     <tr class="cap" id="cap-b"><td></td><td>
+       <strong>b</strong></td><td></td></tr>
+     <tr>
+       <td></td>
+       <td>
+       <a href="tutorial.html#module-bottle"><tt class="xref">bottle</tt></a></td><td>
+       <em></em></td></tr>
+   </table>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  
+
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="#" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_py-modindex';
+      var disqus_title = 'Python Module Index';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/recipes.html b/html/recipes.html
new file mode 100644 (file)
index 0000000..53c2717
--- /dev/null
@@ -0,0 +1,421 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Recipes &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Frequently Asked Questions" href="faq.html" />
+    <link rel="prev" title="Primer to Asynchronous Applications" href="async.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="faq.html" title="Frequently Asked Questions"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="async.html" title="Primer to Asynchronous Applications"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <span class="target" id="module-bottle"></span><div class="section" id="recipes">
+<h1>Recipes<a class="headerlink" href="#recipes" title="Permalink to this headline">¶</a></h1>
+<p>This is a collection of code snippets and examples for common use cases.</p>
+<div class="section" id="keeping-track-of-sessions">
+<h2>Keeping track of Sessions<a class="headerlink" href="#keeping-track-of-sessions" title="Permalink to this headline">¶</a></h2>
+<p>There is no built-in support for sessions because there is no <em>right</em> way to do it (in a micro framework). Depending on requirements and environment you could use <a class="reference external" href="http://beaker.groovie.org/">beaker</a> middleware with a fitting backend or implement it yourself. Here is an example for beaker sessions with a file-based backend:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">bottle</span>
+<span class="kn">from</span> <span class="nn">beaker.middleware</span> <span class="kn">import</span> <span class="n">SessionMiddleware</span>
+
+<span class="n">session_opts</span> <span class="o">=</span> <span class="p">{</span>
+    <span class="s">&#39;session.type&#39;</span><span class="p">:</span> <span class="s">&#39;file&#39;</span><span class="p">,</span>
+    <span class="s">&#39;session.cookie_expires&#39;</span><span class="p">:</span> <span class="mi">300</span><span class="p">,</span>
+    <span class="s">&#39;session.data_dir&#39;</span><span class="p">:</span> <span class="s">&#39;./data&#39;</span><span class="p">,</span>
+    <span class="s">&#39;session.auto&#39;</span><span class="p">:</span> <span class="bp">True</span>
+<span class="p">}</span>
+<span class="n">app</span> <span class="o">=</span> <span class="n">SessionMiddleware</span><span class="p">(</span><span class="n">bottle</span><span class="o">.</span><span class="n">app</span><span class="p">(),</span> <span class="n">session_opts</span><span class="p">)</span>
+
+<span class="nd">@bottle.route</span><span class="p">(</span><span class="s">&#39;/test&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
+  <span class="n">s</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;beaker.session&#39;</span><span class="p">)</span>
+  <span class="n">s</span><span class="p">[</span><span class="s">&#39;test&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;test&#39;</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
+  <span class="n">s</span><span class="o">.</span><span class="n">save</span><span class="p">()</span>
+  <span class="k">return</span> <span class="s">&#39;Test counter: </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">s</span><span class="p">[</span><span class="s">&#39;test&#39;</span><span class="p">]</span>
+
+<span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">app</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="debugging-with-style-debugging-middleware">
+<h2>Debugging with Style: Debugging Middleware<a class="headerlink" href="#debugging-with-style-debugging-middleware" title="Permalink to this headline">¶</a></h2>
+<p>Bottle catches all Exceptions raised in your app code to prevent your WSGI server from crashing. If the built-in <a class="reference internal" href="api.html#bottle.debug" title="bottle.debug"><tt class="xref py py-func docutils literal"><span class="pre">debug()</span></tt></a> mode is not enough and you need exceptions to propagate to a debugging middleware, you can turn off this behaviour:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">bottle</span>
+<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">app</span><span class="p">()</span>
+<span class="n">app</span><span class="o">.</span><span class="n">catchall</span> <span class="o">=</span> <span class="bp">False</span> <span class="c">#Now most exceptions are re-raised within bottle.</span>
+<span class="n">myapp</span> <span class="o">=</span> <span class="n">DebuggingMiddleware</span><span class="p">(</span><span class="n">app</span><span class="p">)</span> <span class="c">#Replace this with a middleware of your choice (see below)</span>
+<span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">myapp</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Now, bottle only catches its own exceptions (<a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a>, <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> and <a class="reference internal" href="api.html#bottle.BottleException" title="bottle.BottleException"><tt class="xref py py-exc docutils literal"><span class="pre">BottleException</span></tt></a>) and your middleware can handle the rest.</p>
+<p>The <a class="reference external" href="http://werkzeug.pocoo.org/documentation/dev/debug.html">werkzeug</a> and <a class="reference external" href="http://pythonpaste.org/modules/evalexception.html">paste</a> libraries both ship with very powerful debugging WSGI middleware. Look at <a class="reference external" href="http://werkzeug.pocoo.org/docs/debug/#werkzeug.debug.DebuggedApplication" title="(in Werkzeug v0.9)"><tt class="xref py py-class docutils literal"><span class="pre">werkzeug.debug.DebuggedApplication</span></tt></a> for <a class="reference external" href="http://werkzeug.pocoo.org/documentation/dev/debug.html">werkzeug</a> and <tt class="xref py py-class docutils literal"><span class="pre">paste.evalexception.middleware.EvalException</span></tt> for <a class="reference external" href="http://pythonpaste.org/modules/evalexception.html">paste</a>. They both allow you do inspect the stack and even execute python code within the stack context, so <strong>do not use them in production</strong>.</p>
+</div>
+<div class="section" id="unit-testing-bottle-applications">
+<h2>Unit-Testing Bottle Applications<a class="headerlink" href="#unit-testing-bottle-applications" title="Permalink to this headline">¶</a></h2>
+<p>Unit-testing is usually performed against methods defined in your web application without running a WSGI environment.</p>
+<p>A simple example using <a class="reference external" href="http://readthedocs.org/docs/nose">Nose</a>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">bottle</span>
+
+<span class="nd">@bottle.route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&#39;Hi!&#39;</span>
+
+<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
+    <span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>Test script:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">mywebapp</span>
+
+<span class="k">def</span> <span class="nf">test_webapp_index</span><span class="p">():</span>
+    <span class="k">assert</span> <span class="n">mywebapp</span><span class="o">.</span><span class="n">index</span><span class="p">()</span> <span class="o">==</span> <span class="s">&#39;Hi!&#39;</span>
+</pre></div>
+</div>
+<p>In the example the Bottle route() method is never executed - only index() is tested.</p>
+</div>
+<div class="section" id="functional-testing-bottle-applications">
+<h2>Functional Testing Bottle Applications<a class="headerlink" href="#functional-testing-bottle-applications" title="Permalink to this headline">¶</a></h2>
+<p>Any HTTP-based testing system can be used with a running WSGI server, but some testing frameworks work more intimately with WSGI, and provide the ability the call WSGI applications in a controlled environment, with tracebacks and full use of debugging tools. <a class="reference external" href="http://www.wsgi.org/en/latest/testing.html">Testing tools for WSGI</a> is a good starting point.</p>
+<p>Example using <a class="reference external" href="http://webtest.pythonpaste.org/">WebTest</a> and <a class="reference external" href="http://readthedocs.org/docs/nose">Nose</a>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">webtest</span> <span class="kn">import</span> <span class="n">TestApp</span>
+<span class="kn">import</span> <span class="nn">mywebapp</span>
+
+<span class="k">def</span> <span class="nf">test_functional_login_logout</span><span class="p">():</span>
+    <span class="n">app</span> <span class="o">=</span> <span class="n">TestApp</span><span class="p">(</span><span class="n">mywebapp</span><span class="o">.</span><span class="n">app</span><span class="p">)</span>
+
+    <span class="n">app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s">&#39;/login&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;user&#39;</span><span class="p">:</span> <span class="s">&#39;foo&#39;</span><span class="p">,</span> <span class="s">&#39;pass&#39;</span><span class="p">:</span> <span class="s">&#39;bar&#39;</span><span class="p">})</span> <span class="c"># log in and get a cookie</span>
+
+    <span class="k">assert</span> <span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;/admin&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s">&#39;200 OK&#39;</span>        <span class="c"># fetch a page successfully</span>
+
+    <span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;/logout&#39;</span><span class="p">)</span>                                 <span class="c"># log out</span>
+    <span class="n">app</span><span class="o">.</span><span class="n">reset</span><span class="p">()</span>                                        <span class="c"># drop the cookie</span>
+
+    <span class="c"># fetch the same page, unsuccessfully</span>
+    <span class="k">assert</span> <span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;/admin&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s">&#39;401 Unauthorized&#39;</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="embedding-other-wsgi-apps">
+<h2>Embedding other WSGI Apps<a class="headerlink" href="#embedding-other-wsgi-apps" title="Permalink to this headline">¶</a></h2>
+<p>This is not the recommend way (you should use a middleware in front of bottle to do this) but you can call other WSGI applications from within your bottle app and let bottle act as a pseudo-middleware. Here is an example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">,</span> <span class="n">route</span>
+<span class="n">subproject</span> <span class="o">=</span> <span class="n">SomeWSGIApplication</span><span class="p">()</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/subproject/:subpath#.*#&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;ALL&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">call_wsgi</span><span class="p">(</span><span class="n">subpath</span><span class="p">):</span>
+    <span class="n">new_environ</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
+    <span class="n">new_environ</span><span class="p">[</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">new_environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;SCRIPT_NAME&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39;/subproject&#39;</span>
+    <span class="n">new_environ</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;/&#39;</span> <span class="o">+</span> <span class="n">subpath</span>
+    <span class="k">def</span> <span class="nf">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">headerlist</span><span class="p">):</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">status</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">])</span>
+        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">headerlist</span><span class="p">:</span>
+            <span class="n">response</span><span class="o">.</span><span class="n">add_header</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">app</span><span class="p">(</span><span class="n">new_environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Again, this is not the recommend way to implement subprojects. It is only here because many people asked for this and to show how bottle maps to WSGI.</p>
+</div>
+<div class="section" id="ignore-trailing-slashes">
+<h2>Ignore trailing slashes<a class="headerlink" href="#ignore-trailing-slashes" title="Permalink to this headline">¶</a></h2>
+<p>For Bottle, <tt class="docutils literal"><span class="pre">/example</span></tt> and <tt class="docutils literal"><span class="pre">/example/</span></tt> are two different routes <a class="footnote-reference" href="#id3" id="id2">[1]</a>. To treat both URLs the same you can add two <tt class="docutils literal"><span class="pre">&#64;route</span></tt> decorators:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/test&#39;</span><span class="p">)</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/test/&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">test</span><span class="p">():</span> <span class="k">return</span> <span class="s">&#39;Slash? no?&#39;</span>
+</pre></div>
+</div>
+<p>or add a WSGI middleware that strips trailing slashes from all URLs:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">class</span> <span class="nc">StripPathMiddleware</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
+  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">app</span><span class="p">):</span>
+    <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">app</span>
+  <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">h</span><span class="p">):</span>
+    <span class="n">e</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">e</span><span class="p">[</span><span class="s">&#39;PATH_INFO&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="p">(</span><span class="n">e</span><span class="p">,</span><span class="n">h</span><span class="p">)</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">app</span><span class="p">()</span>
+<span class="n">myapp</span> <span class="o">=</span> <span class="n">StripPathMiddleware</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+<span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="o">=</span><span class="n">myapp</span><span class="p">)</span>
+</pre></div>
+</div>
+<p class="rubric">Footnotes</p>
+<table class="docutils footnote" frame="void" id="id3" rules="none">
+<colgroup><col class="label" /><col /></colgroup>
+<tbody valign="top">
+<tr><td class="label"><a class="fn-backref" href="#id2">[1]</a></td><td>Because they are. See &lt;<a class="reference external" href="http://www.ietf.org/rfc/rfc3986.txt">http://www.ietf.org/rfc/rfc3986.txt</a>&gt;</td></tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="keep-alive-requests">
+<h2>Keep-alive requests<a class="headerlink" href="#keep-alive-requests" title="Permalink to this headline">¶</a></h2>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">For a more detailed explanation, see <a class="reference internal" href="async.html"><em>Primer to Asynchronous Applications</em></a>.</p>
+</div>
+<p>Several &#8220;push&#8221; mechanisms like XHR multipart need the ability to write response data without closing the connection in conjunction with the response header &#8220;Connection: keep-alive&#8221;. WSGI does not easily lend itself to this behavior, but it is still possible to do so in Bottle by using the <a class="reference external" href="http://www.gevent.org/">gevent</a> async framework. Here is a sample that works with either the <a class="reference external" href="http://www.gevent.org/">gevent</a> HTTP server or the <a class="reference external" href="http://pythonpaste.org/modules/evalexception.html">paste</a> HTTP server (it may work with others, but I have not tried). Just change <tt class="docutils literal"><span class="pre">server='gevent'</span></tt> to <tt class="docutils literal"><span class="pre">server='paste'</span></tt> to use the <a class="reference external" href="http://pythonpaste.org/modules/evalexception.html">paste</a> server:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">gevent</span> <span class="kn">import</span> <span class="n">monkey</span><span class="p">;</span> <span class="n">monkey</span><span class="o">.</span><span class="n">patch_all</span><span class="p">()</span>
+
+<span class="kn">import</span> <span class="nn">time</span>
+<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/stream&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">stream</span><span class="p">():</span>
+    <span class="k">yield</span> <span class="s">&#39;START&#39;</span>
+    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
+    <span class="k">yield</span> <span class="s">&#39;MIDDLE&#39;</span>
+    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
+    <span class="k">yield</span> <span class="s">&#39;END&#39;</span>
+
+<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;0.0.0.0&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span> <span class="n">server</span><span class="o">=</span><span class="s">&#39;gevent&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>If you browse to <tt class="docutils literal"><span class="pre">http://localhost:8080/stream</span></tt>, you should see &#8216;START&#8217;, &#8216;MIDDLE&#8217;, and &#8216;END&#8217; show up one at a time (rather than waiting 8 seconds to see them all at once).</p>
+</div>
+<div class="section" id="gzip-compression-in-bottle">
+<h2>Gzip Compression in Bottle<a class="headerlink" href="#gzip-compression-in-bottle" title="Permalink to this headline">¶</a></h2>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">For a detailed discussion, see <a class="reference external" href="https://github.com/defnull/bottle/issues/92">compression</a></p>
+</div>
+<p>A common feature request is for Bottle to support Gzip compression, which speeds up sites by compressing static resources (like CSS and JS files) during a request.</p>
+<p>Supporting Gzip compression is not a straightforward proposition, due to a number of corner cases that crop up frequently. A proper Gzip implementation must:</p>
+<ul class="simple">
+<li>Compress on the fly and be fast doing so.</li>
+<li>Do not compress for browsers that don&#8217;t support it.</li>
+<li>Do not compress files that are compressed already (images, videos).</li>
+<li>Do not compress dynamic files.</li>
+<li>Support two differed compression algorithms (gzip and deflate).</li>
+<li>Cache compressed files that don&#8217;t change often.</li>
+<li>De-validate the cache if one of the files changed anyway.</li>
+<li>Make sure the cache does not get to big.</li>
+<li>Do not cache small files because a disk seek would take longer than on-the-fly compression.</li>
+</ul>
+<p>Because of these requirements, it is the recommendation of the Bottle project that Gzip compression is best handled by the WSGI server Bottle runs on top of. WSGI servers such as <a class="reference external" href="http://www.cherrypy.org">cherrypy</a> provide a <a class="reference external" href="http://www.cherrypy.org/wiki/GzipFilter">GzipFilter</a> middleware that can be used to accomplish this.</p>
+</div>
+<div class="section" id="using-the-hooks-plugin">
+<h2>Using the hooks plugin<a class="headerlink" href="#using-the-hooks-plugin" title="Permalink to this headline">¶</a></h2>
+<p>For example, if you want to allow Cross-Origin Resource Sharing for
+the content returned by all of your URL, you can use the hook
+decorator and setup a callback function:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">hook</span><span class="p">,</span> <span class="n">response</span><span class="p">,</span> <span class="n">route</span>
+
+<span class="nd">@hook</span><span class="p">(</span><span class="s">&#39;after_request&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">enable_cors</span><span class="p">():</span>
+    <span class="n">response</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s">&#39;Access-Control-Allow-Origin&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s">&#39;*&#39;</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/foo&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">say_foo</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&#39;foo!&#39;</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/bar&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">say_bar</span><span class="p">():</span>
+    <span class="k">return</span> <span class="p">{</span><span class="s">&#39;type&#39;</span><span class="p">:</span> <span class="s">&#39;friendly&#39;</span><span class="p">,</span> <span class="s">&#39;content&#39;</span><span class="p">:</span> <span class="s">&#39;Hi!&#39;</span><span class="p">}</span>
+</pre></div>
+</div>
+<p>You can also use the <tt class="docutils literal"><span class="pre">before_callback</span></tt> to take an action before
+every function gets called.</p>
+</div>
+<div class="section" id="using-bottle-with-heroku">
+<h2>Using Bottle with Heroku<a class="headerlink" href="#using-bottle-with-heroku" title="Permalink to this headline">¶</a></h2>
+<p><a class="reference external" href="http://heroku.com">Heroku</a>, a popular cloud application platform now provides support
+for running Python applications on their infastructure.</p>
+<p>This recipe is based upon the <a class="reference external" href="http://devcenter.heroku.com/articles/quickstart">Heroku Quickstart</a>,
+with Bottle specific code replacing the
+<a class="reference external" href="http://devcenter.heroku.com/articles/python#write_your_app">Write Your App</a>
+section of the <a class="reference external" href="http://devcenter.heroku.com/articles/python">Getting Started with Python on Heroku/Cedar</a> guide:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
+<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&quot;/&quot;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello_world</span><span class="p">():</span>
+        <span class="k">return</span> <span class="s">&quot;Hello World!&quot;</span>
+
+<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&quot;0.0.0.0&quot;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="nb">int</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&quot;PORT&quot;</span><span class="p">,</span> <span class="mi">5000</span><span class="p">)))</span>
+</pre></div>
+</div>
+<p>Heroku&#8217;s app stack passes the port that the application needs to
+listen on for requests, using the <cite>os.environ</cite> dictionary.</p>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Recipes</a><ul>
+<li><a class="reference internal" href="#keeping-track-of-sessions">Keeping track of Sessions</a></li>
+<li><a class="reference internal" href="#debugging-with-style-debugging-middleware">Debugging with Style: Debugging Middleware</a></li>
+<li><a class="reference internal" href="#unit-testing-bottle-applications">Unit-Testing Bottle Applications</a></li>
+<li><a class="reference internal" href="#functional-testing-bottle-applications">Functional Testing Bottle Applications</a></li>
+<li><a class="reference internal" href="#embedding-other-wsgi-apps">Embedding other WSGI Apps</a></li>
+<li><a class="reference internal" href="#ignore-trailing-slashes">Ignore trailing slashes</a></li>
+<li><a class="reference internal" href="#keep-alive-requests">Keep-alive requests</a></li>
+<li><a class="reference internal" href="#gzip-compression-in-bottle">Gzip Compression in Bottle</a></li>
+<li><a class="reference internal" href="#using-the-hooks-plugin">Using the hooks plugin</a></li>
+<li><a class="reference internal" href="#using-bottle-with-heroku">Using Bottle with Heroku</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="async.html"
+                        title="previous chapter">Primer to Asynchronous Applications</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="faq.html"
+                        title="next chapter">Frequently Asked Questions</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/recipes.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="faq.html" title="Frequently Asked Questions"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="async.html" title="Primer to Asynchronous Applications"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_recipes';
+      var disqus_title = 'Recipes';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/routing.html b/html/routing.html
new file mode 100644 (file)
index 0000000..c3d8b18
--- /dev/null
@@ -0,0 +1,330 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Request Routing &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="SimpleTemplate Engine" href="stpl.html" />
+    <link rel="prev" title="Tutorial" href="tutorial.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="stpl.html" title="SimpleTemplate Engine"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="tutorial.html" title="Tutorial"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="request-routing">
+<h1>Request Routing<a class="headerlink" href="#request-routing" title="Permalink to this headline">¶</a></h1>
+<p>Bottle uses a powerful routing engine to find the right callback for each request. The <a class="reference internal" href="tutorial.html#tutorial-routing"><em>tutorial</em></a> shows you the basics. This document covers advanced techniques and rule mechanics in detail.</p>
+<div class="section" id="rule-syntax">
+<h2>Rule Syntax<a class="headerlink" href="#rule-syntax" title="Permalink to this headline">¶</a></h2>
+<p>The <tt class="xref py py-class docutils literal"><span class="pre">Router</span></tt> distinguishes between two basic types of routes: <strong>static routes</strong> (e.g. <tt class="docutils literal"><span class="pre">/contact</span></tt>) and <strong>dynamic routes</strong> (e.g. <tt class="docutils literal"><span class="pre">/hello/&lt;name&gt;</span></tt>). A route that contains one or more <em>wildcards</em> it is considered dynamic. All other routes are static.</p>
+<p class="versionchanged">
+<span class="versionmodified">Changed in version 0.10.</span></p>
+<p>The simplest form of a wildcard consists of a name enclosed in angle brackets (e.g. <tt class="docutils literal"><span class="pre">&lt;name&gt;</span></tt>). The name should be unique for a given route and form a valid python identifier (alphanumeric, starting with a letter). This is because wildcards are used as keyword arguments for the request callback later.</p>
+<p>Each wildcard matches one or more characters, but stops at the first slash (<tt class="docutils literal"><span class="pre">/</span></tt>). This equals a regular expression of <tt class="docutils literal"><span class="pre">[^/]+</span></tt> and ensures that only one path segment is matched and routes with more than one wildcard stay unambiguous.</p>
+<p>The rule <tt class="docutils literal"><span class="pre">/&lt;action&gt;/&lt;item&gt;</span></tt> matches as follows:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="23%" />
+<col width="77%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Path</th>
+<th class="head">Result</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>/save/123</td>
+<td><tt class="docutils literal"><span class="pre">{'action':</span> <span class="pre">'save',</span> <span class="pre">'item':</span> <span class="pre">'123'}</span></tt></td>
+</tr>
+<tr class="row-odd"><td>/save/123/</td>
+<td><cite>No Match</cite></td>
+</tr>
+<tr class="row-even"><td>/save/</td>
+<td><cite>No Match</cite></td>
+</tr>
+<tr class="row-odd"><td>//123</td>
+<td><cite>No Match</cite></td>
+</tr>
+</tbody>
+</table>
+<p>You can change the exact behaviour in many ways using filters. This is described in the next section.</p>
+</div>
+<div class="section" id="wildcard-filters">
+<h2>Wildcard Filters<a class="headerlink" href="#wildcard-filters" title="Permalink to this headline">¶</a></h2>
+<p class="versionadded">
+<span class="versionmodified">New in version 0.10.</span></p>
+<p>Filters are used to define more specific wildcards, and/or transform the matched part of the URL before it is passed to the callback. A filtered wildcard is declared as <tt class="docutils literal"><span class="pre">&lt;name:filter&gt;</span></tt> or <tt class="docutils literal"><span class="pre">&lt;name:filter:config&gt;</span></tt>. The syntax for the optional config part depends on the filter used.</p>
+<p>The following standard filters are implemented:</p>
+<ul class="simple">
+<li><strong>:int</strong> matches (signed) digits and converts the value to integer.</li>
+<li><strong>:float</strong> similar to :int but for decimal numbers.</li>
+<li><strong>:path</strong> matches all characters including the slash character in a non-greedy way and may be used to match more than one path segment.</li>
+<li><strong>:re[:exp]</strong> allows you to specify a custom regular expression in the config field. The matched value is not modified.</li>
+</ul>
+<p>You can add your own filters to the router. All you need is a function that returns three elements: A regular expression string, a callable to convert the URL fragment to a python value, and a callable that does the opposite. The filter function is called with the configuration string as the only parameter and may parse it as needed:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">app</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+
+<span class="k">def</span> <span class="nf">list_filter</span><span class="p">(</span><span class="n">config</span><span class="p">):</span>
+    <span class="sd">&#39;&#39;&#39; Matches a comma separated list of numbers. &#39;&#39;&#39;</span>
+    <span class="n">delimiter</span> <span class="o">=</span> <span class="n">config</span> <span class="ow">or</span> <span class="s">&#39;,&#39;</span>
+    <span class="n">regexp</span> <span class="o">=</span> <span class="s">r&#39;\d+(</span><span class="si">%s</span><span class="s">\d)*&#39;</span> <span class="o">%</span> <span class="n">re</span><span class="o">.</span><span class="n">escape</span><span class="p">(</span><span class="n">delimiter</span><span class="p">)</span>
+
+    <span class="k">def</span> <span class="nf">to_python</span><span class="p">(</span><span class="n">match</span><span class="p">):</span>
+        <span class="k">return</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">match</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">delimiter</span><span class="p">))</span>
+
+    <span class="k">def</span> <span class="nf">to_url</span><span class="p">(</span><span class="n">numbers</span><span class="p">):</span>
+        <span class="k">return</span> <span class="n">delimiter</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="n">numbers</span><span class="p">))</span>
+
+    <span class="k">return</span> <span class="n">regexp</span><span class="p">,</span> <span class="n">to_python</span><span class="p">,</span> <span class="n">to_url</span>
+
+<span class="n">app</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">add_filter</span><span class="p">(</span><span class="s">&#39;list&#39;</span><span class="p">,</span> <span class="n">list_filter</span><span class="p">)</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/follow/&lt;ids:list&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">follow_users</span><span class="p">(</span><span class="n">ids</span><span class="p">):</span>
+    <span class="k">for</span> <span class="nb">id</span> <span class="ow">in</span> <span class="n">ids</span><span class="p">:</span>
+        <span class="o">...</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="legacy-syntax">
+<h2>Legacy Syntax<a class="headerlink" href="#legacy-syntax" title="Permalink to this headline">¶</a></h2>
+<p class="versionchanged">
+<span class="versionmodified">Changed in version 0.10.</span></p>
+<p>The new rule syntax was introduce in <strong>Bottle 0.10</strong> to simplify some common use cases, but the old syntax still works and you can find lot code examples still using it. The differences are best described by example:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="49%" />
+<col width="51%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Old Syntax</th>
+<th class="head">New Syntax</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td><tt class="docutils literal"><span class="pre">:name</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;name&gt;</span></tt></td>
+</tr>
+<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">:name#regexp#</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;name:re:regexp&gt;</span></tt></td>
+</tr>
+<tr class="row-even"><td><tt class="docutils literal"><span class="pre">:#regexp#</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;:re:regexp&gt;</span></tt></td>
+</tr>
+<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">:##</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;:re&gt;</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>Try to avoid the old syntax in future projects if you can. It is not currently deprecated, but will be eventually.</p>
+</div>
+<div class="section" id="routing-order">
+<h2>Routing Order<a class="headerlink" href="#routing-order" title="Permalink to this headline">¶</a></h2>
+<p>With the power of wildcards and regular expressions it is possible to define overlapping routes. If multiple routes match the same URL, things get a bit tricky. To fully understand what happens in this case, you need to know in which order routes are checked by the router.</p>
+<p>First you should know that routes are grouped by their path rule. Two routes with the same path rule but different methods are grouped together and the first route determines the position of both routes. Fully identical routes (same path rule and method) replace previously defined routes, but keep the position of their predecessor.</p>
+<p>Static routes are checked first. This is mostly for performance reasons and can be switched off, but is currently the default. If no static route matches the request, the dynamic routes are checked in the order they were defined. The first hit ends the search. If no rule matched, a &#8220;404 Page not found&#8221; error is returned.</p>
+<p>In a second step, the request method is checked. If no exact match is found, and the request method is HEAD, the router checks for a GET route. Otherwise, it checks for an ANY route. If that fails too, a &#8220;405 Method not allowed&#8221; error is returned.</p>
+<p>Here is an example where this might bite you:</p>
+<div class="highlight-python"><pre>@route('/&lt;action&gt;/&lt;name&gt;', method='GET')
+@route('/save/&lt;name&gt;', method='POST')</pre>
+</div>
+<p>The second route will never hit. Even POST requests don&#8217;t arrive at the second route because the request method is checked in a separate step. The router stops at the first route which matches the request path, then checks for a valid request method, can&#8217;t find one and raises a 405 error.</p>
+<p>Sounds complicated, and it is. That is the price for performance. It is best to avoid ambiguous routes at all and choose unique prefixes for each route. This implementation detail may change in the future, though. We are working on it.</p>
+</div>
+<div class="section" id="explicit-routing-configuration">
+<h2>Explicit routing configuration<a class="headerlink" href="#explicit-routing-configuration" title="Permalink to this headline">¶</a></h2>
+<p>Route decorator can also be directly called as method. This way provides flexibility in complex setups, allowing you to directly control, when and how routing configuration done.</p>
+<p>Here is a basic example of explicit routing configuration for default bottle application:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">setup_routing</span><span class="p">():</span>
+    <span class="n">bottle</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="n">index</span><span class="p">)</span>
+    <span class="n">bottle</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s">&#39;/edit&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="s">&#39;POST&#39;</span><span class="p">],</span> <span class="n">edit</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>In fact, any <tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt> instance routing can be configured same way:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="k">def</span> <span class="nf">setup_routing</span><span class="p">(</span><span class="n">app</span><span class="p">):</span>
+    <span class="n">app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s">&#39;/new&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="s">&#39;POST&#39;</span><span class="p">],</span> <span class="n">form_new</span><span class="p">)</span>
+    <span class="n">app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s">&#39;/edit&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="p">[</span><span class="s">&#39;GET&#39;</span><span class="p">,</span> <span class="s">&#39;POST&#39;</span><span class="p">],</span> <span class="n">form_edit</span><span class="p">)</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+<span class="n">setup_routing</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Request Routing</a><ul>
+<li><a class="reference internal" href="#rule-syntax">Rule Syntax</a></li>
+<li><a class="reference internal" href="#wildcard-filters">Wildcard Filters</a></li>
+<li><a class="reference internal" href="#legacy-syntax">Legacy Syntax</a></li>
+<li><a class="reference internal" href="#routing-order">Routing Order</a></li>
+<li><a class="reference internal" href="#explicit-routing-configuration">Explicit routing configuration</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="tutorial.html"
+                        title="previous chapter">Tutorial</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="stpl.html"
+                        title="next chapter">SimpleTemplate Engine</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/routing.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="stpl.html" title="SimpleTemplate Engine"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="tutorial.html" title="Tutorial"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_routing';
+      var disqus_title = 'Request Routing';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/search.html b/html/search.html
new file mode 100644 (file)
index 0000000..5f52768
--- /dev/null
@@ -0,0 +1,163 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Search &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <script type="text/javascript" src="_static/searchtools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+  <script type="text/javascript">
+    jQuery(function() { Search.loadIndex("searchindex.js"); });
+  </script>
+  
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  <h1 id="search-documentation">Search</h1>
+  <div id="fallback" class="admonition warning">
+  <script type="text/javascript">$('#fallback').hide();</script>
+  <p>
+    Please activate JavaScript to enable the search
+    functionality.
+  </p>
+  </div>
+  <p>
+    From here you can search these documents. Enter your search
+    words into the box below and click "search". Note that the search
+    function will automatically search for all of the words. Pages
+    containing fewer words won't appear in the result list.
+  </p>
+  <form action="" method="get">
+    <input type="text" name="q" value="" />
+    <input type="submit" value="search" />
+    <span id="search-progress" style="padding-left: 10px"></span>
+  </form>
+  
+  <div id="search-results">
+  
+  </div>
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  
+
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_search';
+      var disqus_title = 'Search';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/searchindex.js b/html/searchindex.js
new file mode 100644 (file)
index 0000000..f97e5f6
--- /dev/null
@@ -0,0 +1 @@
+Search.setIndex({objects:{"":{bottle:[16,0,1,""]},"bottle.ResourceManager":{path:[4,3,1,""],add_path:[4,2,1,""],cache:[4,3,1,""],open:[4,2,1,""],lookup:[4,2,1,""]},"bottle.BaseTemplate":{search:[4,7,1,""],render:[4,2,1,""],"__init__":[4,2,1,""],prepare:[4,2,1,""],global_config:[4,7,1,""]},"bottle.Route":{reset:[4,2,1,""],name:[4,3,1,""],prepare:[4,2,1,""],app:[4,3,1,""],rule:[4,3,1,""],method:[4,3,1,""],callback:[4,3,1,""],plugins:[4,3,1,""],config:[4,3,1,""],skiplist:[4,3,1,""],all_plugins:[4,2,1,""]},"bottle.Plugin":{name:[9,3,1,""],setup:[9,2,1,""],api:[9,3,1,""],close:[9,2,1,""],"__call__":[9,2,1,""],apply:[9,2,1,""]},"bottle.FormsDict":{decode:[4,2,1,""],input_encoding:[4,3,1,""],recode_unicode:[4,3,1,""]},stpl:{defined:[8,1,1,""],setdefault:[8,1,1,""],get:[8,1,1,""]},"bottle.WSGIHeaderDict":{raw:[4,2,1,""],cgikeys:[4,3,1,""]},"bottle.LocalRequest":{bind:[4,2,1,""],environ:[4,3,1,""]},"bottle.HTTPResponse":{output:[4,3,1,""]},"bottle.SimpleTemplate":{render:[8,2,1,""],split_comment:[8,7,1,""]},bottle:{load:[4,1,1,""],LocalResponse:[4,4,1,""],app:[4,1,1,""],path_shift:[4,1,1,""],load_app:[4,1,1,""],yieldroutes:[4,1,1,""],cookie_encode:[4,1,1,""],cookie_is_encoded:[4,1,1,""],LocalRequest:[4,4,1,""],BaseTemplate:[4,4,1,""],BaseResponse:[4,4,1,""],AppStack:[4,4,1,""],get:[4,1,1,""],response:[4,5,1,""],template:[4,1,1,""],HTTPResponse:[4,6,1,""],FormsDict:[4,4,1,""],Response:[4,3,1,""],Plugin:[9,4,1,""],cookie_decode:[4,1,1,""],run:[4,1,1,""],HTTP_CODES:[4,5,1,""],WSGIHeaderDict:[4,4,1,""],HeaderDict:[4,4,1,""],Route:[4,4,1,""],Request:[4,3,1,""],BottleException:[4,6,1,""],Bottle:[4,4,1,""],put:[4,1,1,""],post:[4,1,1,""],HTTPError:[4,6,1,""],BaseRequest:[4,4,1,""],parse_auth:[4,1,1,""],default_app:[4,1,1,""],ResourceManager:[4,4,1,""],route:[4,1,1,""],request:[4,5,1,""],MultiDict:[4,4,1,""],parse_date:[4,1,1,""],error:[4,1,1,""],debug:[4,1,1,""],SimpleTemplate:[8,4,1,""],"delete":[4,1,1,""],view:[4,1,1,""]},"bottle.Bottle":{wsgi:[4,2,1,""],add_route:[4,2,1,""],catchall:[4,3,1,""],hook:[4,2,1,""],close:[4,2,1,""],handle:[4,2,1,""],config:[4,3,1,""],resources:[4,3,1,""],run:[4,2,1,""],get:[4,2,1,""],put:[4,2,1,""],post:[4,2,1,""],reset:[4,2,1,""],get_url:[4,2,1,""],route:[4,2,1,""],merge:[4,2,1,""],match:[4,2,1,""],install:[4,2,1,""],error:[4,2,1,""],"delete":[4,2,1,""],mount:[4,2,1,""],uninstall:[4,2,1,""]},"bottle.MultiDict":{getlist:[4,2,1,""],get:[4,2,1,""],getall:[4,2,1,""],replace:[4,2,1,""],getone:[4,2,1,""],append:[4,2,1,""]},"bottle.BaseRequest":{content_length:[4,3,1,""],body:[4,3,1,""],cookies:[4,3,1,""],app:[4,3,1,""],script_name:[4,3,1,""],query:[4,3,1,""],MEMFILE_MAX:[4,3,1,""],GET:[4,3,1,""],forms:[4,3,1,""],json:[4,3,1,""],urlparts:[4,3,1,""],params:[4,3,1,""],MAX_PARAMS:[4,3,1,""],method:[4,3,1,""],get_header:[4,2,1,""],files:[4,3,1,""],auth:[4,3,1,""],remote_route:[4,3,1,""],path_shift:[4,2,1,""],content_type:[4,3,1,""],path:[4,3,1,""],POST:[4,3,1,""],copy:[4,2,1,""],COOKIES:[4,3,1,""],get_cookie:[4,2,1,""],url:[4,3,1,""],remote_addr:[4,3,1,""],headers:[4,3,1,""],environ:[4,3,1,""],is_ajax:[4,3,1,""],query_string:[4,3,1,""],is_xhr:[4,3,1,""],fullpath:[4,3,1,""]},"bottle.LocalResponse":{body:[4,3,1,""]},"bottle.AppStack":{push:[4,2,1,""],pop:[4,2,1,""]},"bottle.BaseResponse":{status:[4,3,1,""],content_length:[4,3,1,""],COOKIES:[4,3,1,""],headerlist:[4,3,1,""],set_cookie:[4,2,1,""],add_header:[4,2,1,""],status_code:[4,3,1,""],charset:[4,3,1,""],status_line:[4,3,1,""],set_header:[4,2,1,""],headers:[4,3,1,""],delete_cookie:[4,2,1,""],content_type:[4,3,1,""],copy:[4,2,1,""],iter_headers:[4,2,1,""],get_header:[4,2,1,""]}},terms:{content_length:4,untrust:8,all:[0,1,2,3,5,8,9,10,4,12,13,14,15,16],four:[4,16,3],jinja2_view:4,prefix:[4,12,9],run_onc:3,sleep:[14,5],dirnam:[15,13],gae:13,authorit:4,sorri:[0,15,16],under:16,f72a7c:3,merchant:1,digit:[15,12,16],everi:[5,4,15,16,9],risk:2,"_lctx":4,upstream:0,affect:[0,10,4,16,9],cookie_encod:4,upload:[1,4,16],direct:[1,4],consequ:[14,16],second:[3,5,8,9,4,12,14,15,16],even:[0,5,8,4,12,13,14,15,16],hide:8,eventlet:13,neg:4,item1:15,"new":[0,3,15,7,8,4,12,13,14,16],net:0,ever:0,metadata:[1,4,16],ongo:14,elimin:13,abov:[0,1,15,8,16],send_imag:16,never:[0,5,12,16],forum_id:16,here:[0,1,2,5,6,7,8,9,11,12,13,14,15,16],defnul:[0,10,11,2,16],tornado:[14,13],debugg:2,path:[3,15,6,8,9,4,12,13,16],testapp:5,interpret:[15,13,8,3],forum:16,anymor:3,datetim:[4,16],permit:1,aka:[11,16],pack:[4,2],portabl:16,joshua:3,get_cooki:[4,16,3],unix:[15,4,16],txt:5,middlewar:[1,5,6,7,4,16],describ:[0,15,9,4,12,16],would:[0,5,6,14,15,16],subpath:5,call:[0,1,3,5,8,9,4,12,13,15,16],recommend:[0,5,4,16,3],type:[0,3,5,9,4,12,14,15,16],until:[0,14,4,16],fastcgi:13,hoffmann:3,relat:[1,11,7,16,9],notic:[1,15,4],hurt:13,warn:[0,15,4,8,16],exce:16,herebi:1,overrul:[4,9],must:[0,3,5,8,9,4,14,15,16],join:[0,12,16],restor:[0,4,16],setup:[10,2,1,5,3,9,12,13,15,16],work:[0,1,5,6,8,9,4,12,13,14,15,16],xhr:5,wors:16,remote_rout:[4,3],root:[9,4,15,16,13],overrid:[10,16,9],give:[15,9],indic:0,unavail:4,want:[0,1,3,5,8,9,4,13,14,15,16],keep:[0,1,10,5,8,9,4,12,15,16],declar:[12,16],end:[10,5,8,9,4,12,13,14,15,16],quot:3,how:[1,5,8,9,12,13,14,15,16],conn:15,answer:[1,14],acasaju:3,subproject:5,perspect:14,updat:[0,1,2,15,9,4,14],mako:[1,3],rebas:[0,8],after:[0,15,4,16,9],befor:[0,1,2,5,9,4,12,14,15,16],wrong:[15,4,16],law:11,demonstr:[15,16],nobreak:8,handl:[10,3,5,8,9,4,13,14,15,16],flupserv:15,third:[14,15,7,16,9],classmethod:[4,8],minim:4,credenti:16,lost:6,greet:[2,16],alias:4,maintain:[0,3,7,8,4,16],environ:[0,3,5,6,9,4,14,15,16],enter:16,first:[0,1,4,15,8,9,11,12,14,16],order:[0,1,3,15,4,12,13,14,16],oper:[15,16],feedback:[0,11],over:[0,9,4,13,14,16],becaus:[0,3,5,4,12,14,16],fifo:7,privileg:4,flexibl:[8,16,12],digest:4,fit:[1,5,16],fix:[0,9,4,6,3],bytecod:8,fetchal:15,complex:[6,8,12],easier:[0,15,3],them:[0,3,5,8,4,14,15,16],thei:[0,3,5,8,4,12,13,14,16],fragment:[4,12],safe:[0,4,16,9],"break":[0,3,8,9,14,16],jinja2:1,interrupt:16,choic:[5,4,16],changelog:[1,3],unpickl:[4,16],sessionmiddlewar:5,timeout:4,each:[0,10,2,3,15,8,9,4,12,13,14,16],debug:[1,2,3,5,7,4,15,16],side:[14,13,4,16,3],servefil:7,mean:[0,4,16,9],gstein:3,appengin:13,impressum:11,admin_app:4,logo:1,extract:4,nutzung:11,network:[4,13],goe:[4,16],diesel:13,content:[1,15,8,4,5,16],rewrit:[0,14],dieser:11,adjust:4,adapt:[1,13,4,15,3],got:[11,3],gunicorn:[13,3],make_app:16,worthwhil:9,situat:[8,16],given:[3,15,8,9,4,12,16],free:[0,1],standard:[1,10,15,8,12,13,14,16],post_id:16,angl:[12,16],traceback:[5,4,16],ist:11,filter:[1,12,16,3],say_foo:5,iso:16,confus:[0,4,16],bite:12,token:6,rang:[4,16,3],render:[14,4,7,8,16],independ:13,thereof:16,necess:15,restrict:[1,8,16],hook:[1,5,4,9],alreadi:[0,10,5,8,9,15,16],messag:[14,15,9,16,13],massiv:14,handler_class:14,primari:15,top:[0,5,4,16],sometim:[0,15,4,16,13],fiction:16,isalpha:16,master:[0,16],too:[0,15,6,8,11,4,12,14,16],ioerror:4,listen:[5,4,15,16,13],consol:[1,2],namespac:[9,4,8,16,3],tool:[14,5,16],lighttpd:13,technic:0,target:4,cgikei:4,provid:[1,2,5,7,9,4,12,13,16],project:[0,1,3,5,7,11,12,14,15,16],minut:0,websocket:[1,14],add_head:[5,4,16],mind:[4,8,16,9],raw:[15,4,16,3],pylon:6,"__main__":5,seen:15,seem:3,seek:[5,4],wsgiscriptalia:[15,13],wollrath:3,brandon:3,contact:[11,12,16],fname:9,edit_item:15,transmit:16,simplifi:[10,12,16],germani:11,though:[0,12,16,9],usernam:16,object:[10,2,1,5,3,7,9,4,13,14,15,16],regular:[3,15,6,4,12,16],letter:12,bytesio:4,sub:[8,16],tradit:14,simplic:[8,16],don:[0,2,3,5,8,9,4,12,14,16],simplif:9,doc:[0,9],doe:[0,10,5,9,4,12,13,14,15,16],bracket:[8,16,12],wildcard:[1,4,12,16,3],mod_proxi:13,unchang:16,sum:16,dot:[11,3],wild:[15,3],introspect:[4,9],opposit:12,random:13,syntax:[1,3,15,6,8,4,12,16],mako_templ:4,identifi:[12,16],involv:[0,1,4,8,14],absolut:[4,6,3],submit:[0,1,15,16],layout:8,open_db:16,explain:[15,8,16,9],configur:[0,1,2,10,15,3,9,4,12,13,16],apach:[15,6,13],"_environ":3,gzipfilt:5,busi:14,"__call__":[5,9],folder:16,predecessor:12,set_head:[4,16],googlegroup:0,watch:[0,15,11],report:9,bar:5,ietf:5,patch:[0,1,9,14,3],reload:[15,4,16],bad:[4,9],steal:16,fair:15,serve_forev:14,mandatori:[0,4],result:[15,4,8,16,12],zwecken:11,respons:[1,2,3,5,7,9,4,14,15,16],fail:[4,12,16],import_str:4,best:[0,5,4,12,16],subject:1,awar:8,said:15,databas:[10,3,15,7,9,13,14,16],sigint:16,outstand:10,simplest:12,getunicod:16,awai:[15,16],irc:[0,16],strippathmiddlewar:5,attribut:[9,4,16,3],reddit:3,extend:[15,9,7,3],ask:[1,5,6,16],extens:[15,4],lazi:2,baserequest:[4,16,3],protect:[15,4,16,3],easi:[0,15,8,9,4,13,14,16],irregular:0,simpletempl:[1,4,8,16,3],howev:[1,16,9],against:5,und:11,brad:3,login:[5,16],com:[0,10,2,15,6,13,14,16],col:15,con:15,asctim:4,written:[15,13,3],trust:[0,16],assum:[0,15,4,16],summar:9,duplic:4,liabil:1,attribu:4,add_rout:4,three:[0,3,15,8,4,12,13,16],been:16,wsgiprocessgroup:[15,13],much:[15,11,16],interest:[0,1,16],basic:[0,1,15,8,9,4,12,16],accpet:3,quickli:8,life:15,suppress:[4,8],worker:14,new_task:15,argument:[10,15,8,9,4,12,16],multithread:4,child:16,"catch":[5,15,16],teapot:4,davi:3,ident:[12,16],oher:3,adress:15,servic:[4,6,13],properti:[4,3],neat:16,after_request:[5,4],spawn:[14,16],bin:[0,16],pyramid:13,kwarg:[4,8,9],conf:9,sever:[0,5,4,8,16],betreib:11,on_data:14,perform:[3,5,9,12,13,14,15,16],suggest:[16,9],make:[0,3,5,8,11,4,13,14,9,15,16],transpar:[4,3],drawback:13,split:[0,5,12],folgenden:11,complet:[0,1,15,16,3],fairli:[15,16],rais:[2,3,5,8,9,4,12,15,16],studi:11,kept:[14,15],scenario:[8,16],max_param:4,thu:[15,16],kyle:3,inherit:8,client:[4,14,6,16,3],thi:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],gzip:[1,5],programm:16,everyth:[4,6,16],http_code:4,left:[8,16],evalexcept:5,protocol:[4,16],just:[0,5,8,9,4,13,14,15,16],header_templ:8,yet:[0,8,16],languag:[15,11,2,16,8],previous:[4,12,16],xmlhttprequest:[4,16],expos:[14,16],spread:[13,3],board:15,els:[14,15,2,16,8],save:[15,5,4,12,16],explanatori:16,transit:3,applic:[0,1,2,3,5,6,7,9,10,4,12,13,14,15,16],mayb:15,preserv:8,stpl:[8,3],httprespons:[5,4,16,3],apart:16,measur:[14,9],to_python:12,specif:[0,5,9,4,12,13,14,16],filenam:[4,10,6,16],manual:[0,15,16,13],change_dbfil:9,joegest:3,sebastian:3,underli:4,www:[5,4,15,13],right:[0,1,5,6,8,4,12,13,15,16],old:[0,3,15,11,4,12,13,16],thankfulli:14,deal:[1,4],stopiter:14,somehow:[15,16],dead:14,resolv:[0,4],neve:3,intern:[4,8,16],meinheld:[13,3],bore:16,successfulli:[5,15],autocommit:[10,9],insensit:[10,4,16],bottom:0,untersagt:11,subclass:[4,2,16,3],track:[0,1,5],tracker:0,unit:[1,5],handle_websocket:14,condit:1,foo:5,fieldstorag:[4,16],localhost:[1,5,13,14,15,16],core:[7,16,13],plu:0,cork:7,promot:0,repositori:[0,1],post:[3,15,4,12,5,16],chapter:[1,15,16],postgresql:10,iter_head:4,surround:[15,8],simul:[14,8],is_xhr:4,produc:[8,16],"float":[12,15,8,16,3],encod:[4,8,16,3],bound:4,werkzeug:[5,7,2,3],down:[0,13],sub_templ:8,monkei:[14,5,9],wrap:[4,8,16,9],storag:4,hallo:2,accordingli:[4,13],git:[0,1,2,10],wai:[0,5,6,8,9,4,12,13,15,16],overus:16,support:[0,1,2,3,5,8,10,4,13,15,16],transform:[12,16,13],why:[0,14],avail:[0,1,3,15,7,8,9,4,13,16],width:8,request_method:4,editor:15,overhead:[14,9,13,16,3],gil:13,interv:[0,4],fork:[0,14,2,13],head:[14,4,8,16,12],form:[1,3,15,6,4,12,16],offer:[0,15,16,3],sendfil:16,forg:[4,16],sqlalchemi:7,"true":[10,5,8,9,4,14,15,16],freenod:0,reset:[5,4,9],call_wsgi:5,bugfix:[0,3],depreci:0,maximum:[4,16],tell:[0,3,15,9,13,16],featur:[0,2,3,5,6,8,14,15,16],classic:13,latin9:16,exist:[0,10,2,3,15,4,16],ship:[5,15,13],check:[15,8,16,12],encrypt:[4,16],tip:16,jona:3,test:[0,1,10,5,9,13,15,16],webob:3,unlimit:[14,13],node:14,geton:4,intend:[0,1,16],pywsgi:14,intens:13,intent:[4,16],consid:[0,6,12,16,3],sql:[10,15],outdat:0,receiv:[0,14,15,3],longer:5,furthermor:15,anywher:8,pseudo:[14,5],ignor:[1,5,9,16,3],time:[0,3,5,8,9,4,13,14,15,16],push:[0,5,4,16],lastrowid:15,backward:[0,9,3],concept:[15,9,16,13],chain:8,skip:[0,15,4,16,9],test_db:10,global:[9,4,15,16,13],focus:0,telefon:11,signific:16,primer:[1,5,14],row:[10,15,16,9],decid:[11,16],middl:[14,5],depend:[0,1,5,6,9,4,12,15,16],appstack:[4,16],flash:7,readabl:[15,8],ttingen:16,query_str:[4,16],isinst:[16,9],sourc:[0,1,4,8,11,16],string:[3,15,8,9,4,12,14,16],hellkamp:[1,11,3],word:[1,3,15,9,4,14],exact:[0,12],cool:0,level:[14,4,16],good_html:3,die:11,gui:11,iter:[14,4,16],item:[10,15,4,12],unsupport:4,greenlet:[1,14,13],kolechkin:3,cooki:[1,5,4,16,3],div:8,prevent:[14,5,4,8,16],sign:[4,12,16,3],memfile_max:4,tpl_name:4,port:[1,10,5,4,13,14,15,16],appear:16,scaffold:6,cheetah_view:4,current:[3,15,8,9,4,12,14,16],response_bodi:4,portnumb:15,on_finish:14,block_cont:8,gener:[0,1,15,7,8,4,16],unauthor:[5,4],satisfi:4,explicitli:[14,15,8,16,9],modif:16,send_fil:[16,3],address:[15,6,9,4,13,16],along:[4,15,6,16],wait:[14,5,13],shift:4,dabovil:3,queue:[14,7],behav:[14,4,16],bob:16,commonli:16,regardless:16,extra:[0,7,16],tweak:[0,15],modul:[1,2,10,15,3,4,13,14,16],prefer:[15,16,9],bjoern:[1,13,3],visibl:[0,15,4],instal:[0,1,2,10,15,3,7,9,4,13,16],http_:4,memori:[10,4,16,9],sake:[15,8,16],univers:11,visit:[15,11,16],live:[0,4],handler:[14,4,16,13],value2:16,web2pyd:7,checkout:0,peopl:[5,15,3],claus:16,templat:[3,1,10,15,6,8,9,4,13,16],scharenberg:3,rogereren:3,easiest:[16,13],content_typ:[4,16],fly:5,prepar:[4,13],"ausdr\u00fccklich":11,uniqu:[15,9,12,16,3],imper:15,can:[0,10,3,5,8,9,4,12,13,14,15,16],purpos:[1,15,8,16],problemat:8,claim:1,favourit:4,encapsul:3,stream:[14,5,15],backslash:[8,3],agent:16,topic:16,critic:[0,3],abort:[14,16],occur:[10,16],alwai:[9,4,15,16,13],multipl:[15,8,4,12,13,16],wsgi2:13,wsgi1:13,charset:[4,16],write:[0,3,5,8,9,4,14,15,16],server_stat:16,pure:16,cache_db:10,map:[1,5,4,12,16],product:[0,5,15,16,13],max:15,clone:[0,10,2],make_t:15,usabl:[4,16],commit:[0,10,15,9],mai:[0,3,5,7,8,9,4,12,13,15,16],drastic:3,data:[1,3,5,9,4,13,14,15,16],grow:16,practic:[16,9],johnson:3,favorit:[15,11,13],rollin:3,inform:[0,3,15,6,9,4,16],"switch":[9,4,12,13,14,16],combin:[15,4,16],block:[14,4,8,16],yieldrout:4,hello_again:16,macaron:7,notaccept:2,brain:4,noteworthi:3,still:[0,5,9,4,12,14,15,16],mainli:15,dynam:[1,3,15,6,12,5,16],entiti:4,conjunct:5,group:[15,12,13],thank:[14,3],url_schem:6,precondit:4,yaml:13,window:[15,4,16],test_webapp_index:5,curli:[15,8],mail:[0,1,3,9,11,16],main:[0,15,8,4,14,16],non:[0,2,3,15,8,9,4,12,13,14,16],bottle_child:16,initi:4,cheetah:1,now:[0,3,5,8,9,14,15,16],provision:16,discuss:[0,5],nor:[15,4,16],introduct:[0,15],parse_auth:4,term:[15,4],name:[0,1,2,3,15,6,8,9,10,4,12,13,16],config:[4,12,16,9],drop:[5,3],separ:[0,15,8,9,4,12,16],did:15,rwxrwx:3,compil:[4,8,16],domain:[4,16],replac:[2,3,5,8,9,4,12,14,15],individu:[14,16],continu:[14,4,16,9],ensur:[4,12,16,9],backport:0,year:11,urlpars:4,happen:[14,4,12,16],urlpart:[4,3],shown:15,accomplish:5,profil:[11,16],correct:[8,16],earlier:8,get_head:4,ort:11,getcwd:4,ajax:[14,4,16],orm:[6,7],mime:[15,16],carl:3,org:[5,4,16,3],"byte":[14,15,4,16,3],card:3,care:16,reusabl:7,recod:4,setdefault:[8,3],synchron:[1,14],thing:[0,15,6,12,14,16],place:[15,3],router:[9,4,12,3],ture:4,jaimi:3,think:[15,9],frequent:[1,5,6,16],lambda:14,origin:[0,5,8,9,4,16],directli:[0,15,8,9,4,12,13,16],onc:[0,10,2,5,8,9,4,13,14,15,16],https_app:6,yourself:[5,15,16,3],websocketerror:14,strass:11,oppos:16,open:[0,10,4,15,11,14,16],predefin:[4,16],size:[14,15,4],cherrypyserv:15,ian:3,silent:3,caught:4,basetempl:[4,8],citi:16,necessarili:15,draft:9,circl:14,bottleexcept:[5,4],proposit:5,conveni:[1,4,16],friend:14,pocoo:4,especi:13,copi:[1,5,4,16],specifi:[8,9,4,12,13,16],blacklist:16,github:[0,10,11,2,16],enclos:[12,16],mostli:[4,12,3],holder:1,than:[1,5,9,4,12,13,14,15,16],png:[6,16],greenle:3,serv:[15,7,16,13],wide:[16,9],list_filt:12,configdict:[4,3],cool_featur:0,balanc:[4,6,13],were:[0,3,9,4,12,16],posit:[4,11,12],browser:[1,2,15,4,14,5,16],pre:[0,13],sai:[15,8],nicer:15,ani:[0,1,10,5,8,9,4,12,13,14,15,16],hello_templ:16,doctyp:14,ambigu:12,saw:15,engin:[1,10,15,3,8,4,12,13,16],techniqu:12,all_plugin:4,moreov:4,billma:3,note:[0,1,3,5,9,4,14,15,16],forc:[4,16,9],take:[5,9,4,13,15,16],noth:[8,16],channel:[0,14,16],santiago:3,sure:[0,5,9,4,13,15,16],"4kb":4,normal:[0,14,15,4,16],buffer:[14,4],price:12,compress:[1,5],sublicens:1,pair:[8,16],homepag:[1,13],misconfigur:16,icon:6,latex:0,renam:3,rescu:[1,14],later:[0,10,15,12,14,16],http_x_forwarded_host:6,"ausschlie\u00dflich":11,headerlist:[5,4],runtim:[1,9,13,16,3],pattern:[14,6],show:[10,5,8,9,12,14,15,16],german:11,cheap:[14,13],concurr:[14,13],permiss:[1,16],corner:5,xml:6,onli:[0,3,5,6,8,9,4,12,13,14,15,16],slow:[16,13],transact:10,activ:[0,16,9],jinja2_templ:4,dict:[10,4,8,16,3],hello_world:5,offici:0,variou:[15,16],get:[0,1,2,3,4,5,6,8,9,11,12,13,14,15,16],cannot:[0,14,9],requir:[0,1,2,10,4,5,11,14,16],mapper:7,yield:[14,5,4,16],todo_list:15,bad_html:3,aris:1,where:[10,15,12,16,9],summari:15,wiki:[4,16,9],cookie_decod:4,sean:3,urlarg:4,detect:[15,16],review:15,enough:[14,5,16,9],between:[15,8,9,4,12,13,14,16],freder:3,"import":[0,1,2,3,5,8,9,10,4,13,14,15,16],across:16,august:11,check_login:16,cycl:[10,4],base_templ:8,come:[8,16],quiet:[15,4],contract:1,tutori:[1,15,4,12,13,16],mani:[3,5,8,4,12,14,15,16],among:9,pop:[4,16],colon:[15,16],masklinn:3,poll:14,damag:1,better:[15,3],marc:[11,8,3],kontaktdaten:11,oder:11,mark:[0,15,8,3],cheetah_templ:4,thousand:14,rubi:11,bonjour:2,those:15,sound:12,form_new:12,patch_al:[14,5],mount:[4,16,3],trick:[16,13],cast:[15,4],invok:[14,4,16],advantag:13,wsgiheaderdict:[4,16],henc:16,marcel:[1,11,3],wsgiref:[4,16,13],myapp:[5,16,13],krampf:3,"__init__":[5,4,9],httpserver:13,sigurd:3,author:[1,11,7,8],branko:3,same:[10,3,5,8,9,4,12,13,15,16],epoch:4,html:[0,3,15,8,4,14,16],timestamp:[4,16],eventu:[12,16],mywebapp:5,exhaust:[14,4],finish:14,utf8:[4,8,16],nest:16,confidenti:16,noisefloor:15,driven:10,capabl:1,improv:[16,3],extern:[4,16,13],appropri:[16,9],cherri:0,markup:15,justifi:9,without:[0,1,5,4,13,14,15,16],simplecooki:4,serveradapt:4,manifold:16,execut:[10,15,8,9,4,5,16],when:[0,15,12,16,13],rest:[15,5,8,16],kill:16,touch:16,speed:[9,5,4,8,3],zajonc:3,except:[0,2,3,5,9,4,14,15,16],param:4,blog:[0,16],versa:4,stopwatch:9,vulner:16,earli:[14,16,13],around:[14,16],read:[0,2,3,15,9,4,14,16],web2pi:7,traffic:15,world:[1,5,8,13,14,16],mod:4,best_match:2,whitespac:8,johann:3,integ:[3,15,9,4,12,16],server:[10,2,1,5,3,4,13,14,15,16],benefit:14,either:[3,5,4,13,14,15,16],output:[15,4,8,16,3],manag:[14,15,4,16,13],parse_d:4,authent:[15,4,7],leftblock:8,easili:[5,15,16,3],definit:16,achiev:[15,9,16,3],evolv:9,exit:16,complic:[12,13],refer:[1,15,9,4,13,16],power:[2,5,8,12,13,16],inspect:[5,2,9],unsuccessfulli:5,broken:[4,9],hooksplugin:9,fulli:[4,12],"__name__":5,"throw":15,deflat:5,get_url:4,addition:[14,4,16,3],stand:8,act:[5,13],error404:16,effici:[16,9],status_cod:[4,3],strip:[5,4,15],your:[0,1,2,3,5,6,9,10,4,12,13,14,15,16],log:[5,16],start:[0,1,3,4,5,8,9,11,12,13,14,15,16],interfac:[0,3,15,9,4,13,16],low:[14,16],lot:[0,3,15,11,4,12,13,14,9,16],submiss:16,media:4,bottl:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],new_environ:5,tupl:[10,15,4],bundl:[9,3],mistake404:15,mistake403:15,cryptograph:[4,16],congratul:15,spice:15,pull:0,reappli:0,possibl:[0,3,5,6,8,4,12,14,15,16],"default":[10,2,3,15,8,9,4,12,13,16],start_respons:[4,5,6],stacktrac:15,embed:[1,5,8],routenam:4,connect:[1,10,5,9,4,13,14,15,16],rechtlichen:11,gone:[4,3],creat:[0,15,8,9,4,14,16],certain:[14,15,9],file:[0,1,3,5,7,9,4,13,15,16],fill:4,again:[0,5,9,4,13,15,16],googl:[0,1,13,3],collin:3,setup_rout:12,event:[1,16,14],field:[4,12,16],valid:[15,6,4,12,13,5,16],collis:9,you:[0,1,2,3,5,6,7,8,9,10,4,12,13,14,15,16],nichol:3,"8ccb2d":3,briefli:[14,9],bugfix_nam:0,pool:14,reduc:[0,3],directori:[1,15,6,4,13,16],descript:[9,16,13],tricki:[15,12,13],mimic:4,adam:3,potenti:13,escap:[12,15,8,3],cpu:[14,13],represent:8,myrout:15,forget:[14,4],forbidden:[15,4],lack:8,mainhandl:14,abil:[14,5,15,16],follow:[0,1,2,10,15,3,8,9,4,12,14,16],disk:5,yourapp:13,cachemod:4,hotqueu:7,script_nam:[5,4,3],articl:[1,16,14],tail:4,program:15,rstrip:5,introduc:[0,15,12,16,3],"case":[0,1,10,5,3,8,9,4,12,14,15,16],straightforward:5,fals:[5,4,2,16,8],util:[1,2,15,4,13,16],candid:0,mechan:[5,12],fall:16,veri:[0,10,5,8,9,13,14,15,16],bottleneck:[15,16,13],list:[0,1,3,15,7,8,9,4,12,13,16],sane:16,stderr:4,small:[0,3,5,6,11,14,15,16],status_lin:[4,3],vanilla:8,sierakowski:3,sync:0,past:[1,5,6,13,15,16],zero:4,design:[0,14,6,16,13],pass:[0,10,5,8,9,4,12,14,15,16],further:[0,15,16],haag:3,excit:15,what:[0,3,15,12,14,16],schertel:3,sqlite_plugin:16,sun:3,section:[15,5,12,16],split_com:8,abl:[0,3,15,9,4,16],brief:15,delet:[0,4,16,3],version:[0,10,2,3,15,9,4,13,16],"public":[0,15,6,16],full:[3,5,6,8,4,13,15,16],unmodifi:[1,4,9],behaviour:[0,5,12,3],unstabl:1,restricted_area:16,method:[3,5,7,8,9,4,12,15,16],modifi:[1,15,4,12,16],valu:[10,3,5,6,8,9,4,12,15,16],search:[0,6,9,4,12,16],ahead:16,memcach:7,prior:15,amount:14,pick:0,action:[1,15,8,12,5,16],via:[1,15,9,16,13],show_wiki_pag:16,castfilt:4,baserespons:[4,3],deprec:[4,12,16,3],json1:15,karg:4,select:[10,15,9,16,13],distinct:[4,16],stdout:4,regist:4,two:[0,10,5,8,4,12,15,16],app_reset:4,minor:0,more:[5,7,8,9,4,12,13,14,15,16],debuggedappl:[5,2],stick:16,particular:1,known:[1,15,8,16],cach:[10,3,5,8,9,4,15,16],none:[4,8,16,9],endpoint:14,damien:3,der:11,dev:0,histori:0,remain:4,rfc850:4,dem:11,ning:3,learn:[0,1,15,8,16],def:[10,2,1,5,6,8,9,4,12,14,15,16],cherrypi:[1,5,15,16,13],integrityerror:9,share:[0,14,5,9,13],accept:[0,15,6,9,4,14,16],login_submit:16,phrase:[4,3],accept_languag:2,cours:[1,15,16,9],goal:[1,15],secur:[0,4,2,16,3],rather:[14,5],anoth:[0,3,15,8,9,4,16],comfort:14,snippet:[5,6],mvc:6,simpl:[1,5,7,4,14,15,16],css:[5,16],resourc:[5,4,16],referenc:16,reflect:6,develop:[0,1,3,15,7,9,13,16],makotempl:4,associ:[1,15,16,9],"short":[0,15,8,16],footer:8,row_factori:9,onto:0,django:4,caus:[14,8,16,9],callback:[10,1,5,3,9,4,12,14,16],shade:15,alphabet:3,help:[0,3,15,6,7,8,9,4,14,16],max_ag:[4,16],soon:[0,4,9,11,14,16],through:[0,15,16,13],paramet:[3,15,8,9,4,12,13,16],style:[15,1,5,8],brows:5,pend:0,bypass:16,might:[0,6,9,4,12,14,16],tri:[5,15,13],good:[0,5,9,15,13],"return":[1,2,3,5,6,8,9,10,4,12,14,15,16],headerdict:4,framework:[1,3,5,6,7,13,14,15,16],detach:14,recode_unicod:4,document:[0,1,3,15,8,12,13,14,16],say_hello:2,dictrow:[10,9],refresh:4,micro:[1,5,6,16],contact_pag:16,compris:16,found:[10,3,6,8,9,4,12,16],unicod:[4,16,3],harm:8,do_upload:16,hard:[0,1,14],idea:[0,14,15,9,13],realli:[0,14,15,16],expect:[0,10,15,9,4,14],todo:[1,15],orient:16,"f\u00fcr":11,robert:3,publish:1,footnot:[1,5],print:8,labb:3,proxi:[4,6,16,13],advanc:[6,7,2,16,12],guess:[15,4,16],reason:[3,15,9,4,12,13,16],base:[0,1,3,5,7,8,9,4,13,14,15,16],put:[3,15,9,4,14,16],basi:[10,9],onopen:14,thread:[0,2,15,9,4,13,14,16],wtform:[4,16,3],perman:4,cookie_is_encod:4,lifetim:16,assign:[15,16,3],major:0,obviou:15,malici:[4,16],feel:[1,14],exchang:15,number:[0,5,4,12,13,14,15,16],placehold:6,roesslein:3,done:[0,15,6,12,9],construct:[15,8],stabl:[0,1,4,16,13],miss:[4,9,6,16,3],differ:[0,10,5,8,9,4,12,13,14,15,16],script:[1,5,4,13,14,15,16],interact:[15,2],least:[0,15,16],cheetahtempl:4,statement:[15,8],scheme:4,store:[15,4,16,9],option:[0,10,2,3,15,8,9,4,12,13,16],behind:[4,6,11],websockethandl:14,part:[0,10,3,15,7,9,4,12,13,16],bidirect:14,off:[0,5,4,12,16],wieland:3,kind:[1,2,16],whenev:[4,16],remot:0,remov:[3,15,8,9,4,16],voltron:3,stall:14,str:[15,4,12,16,9],balancermemb:13,comput:11,seth:3,load_app:4,packag:[0,15,7,4,13,14,16],form_edit:12,gala:3,before_request:4,breakthebottl:3,"null":15,karl:3,sell:1,built:[1,2,3,5,7,8,9,4,13,14,15,16],equival:0,remote_addr:[4,16,3],self:[10,5,9,4,14,16],showitem:10,also:[5,9,4,11,13,15,16,12],build:[0,1,6,9,4,13,16],brace:15,to_url:12,distribut:[0,1,15],exec:9,previou:[14,3],reach:14,most:[0,10,3,5,9,4,13,14,15,16],virus:16,path_info:[5,4],maco:15,charg:1,localrequest:4,exc:16,clear:[9,4,16,3],tpl:[15,8,16],cover:[1,12,16],ext:[10,4,2],clean:[0,1,8],pars:[4,12,16],latest:[0,1,2,16,10],awesom:14,wsgi:[1,2,3,5,6,4,13,14,15,16],alphanumer:[12,3],session:[1,5,4,16],worri:[8,16],font:0,fine:[0,15,16,13],find:[15,4,12,16,9],impact:14,access:[10,1,5,3,8,9,4,13,15,16],pretti:[14,15],my_ip:16,solut:[14,15,6,16],retun:4,show_ip:16,wsgidaemonprocess:[15,13],login_form:16,goldfaber3012:3,hit:[4,12,16],unus:4,"__file__":[15,4,13],express:[1,3,15,6,8,4,12,16],say_bar:5,autojson:4,nativ:[4,3],xb6ttingen:16,fastest:13,zombat:3,liabl:1,restart:[15,16,9],keyword:[10,8,9,4,12,16],rfc:[5,4],common:[1,3,5,6,8,4,12,13,14,15,16],send_stat:16,wrote:15,set:[0,10,2,3,15,6,7,8,9,4,13,16],sipo:3,mutabl:9,see:[0,3,5,8,9,4,14,15,16],arg:[4,8,9],close:[10,5,8,9,4,14,15,16],analog:8,someth:[4,15,11,8],topmost:3,greg:3,fcamel:3,hold:[15,4],experi:11,formsdict:[4,16,3],altern:[15,7,2,16],signatur:[4,16],tristan:3,numer:[4,3],javascript:[4,14,15,11,16],isol:16,lowercas:4,infastructur:5,solv:[0,16],session_opt:5,popul:16,both:[0,10,5,9,4,12,13,14,15,16],last:[0,10,15,9,4,16],delimit:12,alon:[8,16],context:[1,2,3,5,9,16],pdf:[0,16],whole:[0,14,9,16,3],load:[3,15,6,4,13,16],simpli:[0,15,16],point:[0,1,5,9,4,14,15,16],instanti:4,root_app:4,header:[1,3,5,6,8,9,4,16],littl:15,linux:[0,15],mistak:15,backend:[5,16,13],static_dir:13,due:[14,5,13],empti:[14,4,8,16],whom:1,secret:[4,16],unambigu:12,imag:[5,6,16,13],fapws3:[1,15,13],fritz:3,partli:13,func:4,demand:[9,4,16,3],repetit:[0,16],wsgiserv:[14,16,13],convers:4,remote_us:4,look:[5,7,9,4,13,14,15,16],frozen:0,straight:14,"while":[0,15,8,9,14,16],match:[3,15,6,4,12,16],behavior:[5,4,8,16,9],error:[10,2,3,15,6,9,4,12,16],anonym:3,everyon:[0,14],loop:14,expir:[4,16],propag:5,pound:13,readi:[0,6,16,13],rfc1123:4,itself:[2,15,8,9,5,16],"g\u00f6ttingen":[11,16],decor:[3,15,9,4,12,5,16],grant:1,webtest:5,decod:[4,16,3],sqlite3:[10,15,7,9],mod_wsgi:[15,6,13],conflict:[0,4,9],higher:[15,4],wsock:14,"\u00e4hnlichen":11,optim:[1,9,13,16,3],painless:16,alert:14,moment:4,temporari:[0,4],user:[1,5,9,4,13,15,16],robust:13,specialis:4,stack:[4,5,6,16],recent:[0,4,16],noninfring:1,task:[15,16,13],junod:3,kraken:3,pickl:[4,16,3],person:[0,1,15],expens:[14,13],explan:5,routereset:9,openli:0,wickman:3,morsel:4,recognis:8,mysql:10,cut:16,evalex:2,shortcut:[4,16],global_config:4,input:[15,4,8,16],subsequ:[4,9],pasteserv:15,marco:3,obsolet:3,format:[15,16],big:[5,4,16],api_vers:13,insert:[15,6,16],bit:[12,13],stranger:[8,16],signal:16,cur_data:15,httponli:[4,16],collect:[0,1,5,7,16],popular:[5,4],flup:[15,13],often:[5,16],some:[0,3,5,6,8,9,4,12,13,14,15,16],back:[0,10,14,16,13],sampl:5,virtualenv:[0,16],scale:15,shall:1,pep:[14,4],per:[10,9,4,16,14],larg:[15,4],slash:[1,5,6,4,12,15,16],nose:5,cgi:[13,4,16,3],run:[0,1,10,5,6,3,4,13,14,15,16],step:[0,15,12],prerequisit:0,"tom\u00e1":3,meantim:0,wget:16,unicodeerror:16,af93ec:3,prove:0,plai:16,degoi:3,wsgiapplicationgroup:[15,13],dialog:16,stuart:3,showpag:9,plan:[0,7],real:[15,6,8,9,4,11,14],add_path:4,within:[15,8,9,4,13,5,16],jinja2templ:4,contributor:[1,3],announc:0,occupi:14,span:8,question:[1,6,7,16,11],fast:[1,5,6,8,13,16],custom:[3,6,9,4,12,16],heroku:[1,5],includ:[0,1,2,15,8,4,12,14,16],forward:[14,15,4,16,13],properli:[15,9],verb:16,rackham:3,link:[1,16],newer:[4,16],line:[3,15,8,9,4,14,16],murphi:3,utc:4,utf:4,iuri:3,consist:[10,4,12,16],intim:5,test_functional_login_logout:5,highlight:15,similar:[0,3,8,9,4,12,13,14,16],debugplugin:16,constant:4,parser:[8,3],repres:4,"char":[15,16],incomplet:[13,16,3],chat:[0,14],titl:[8,16],codec:16,fixed_app:6,nice:[15,16],localrespons:4,is_ajax:[4,16],lend:5,mongodb:7,meaning:16,enctyp:16,algorithm:5,vice:4,mimetyp:[15,16],virtualhost:[15,13],far:[15,11],fresh:16,hello:[1,2,5,8,4,12,14,16],prototyp:[10,6],code:[0,1,3,4,5,8,9,11,12,15,16],partial:[4,3],edg:4,queri:[13,4,15,16,3],privat:0,follow_us:12,friendli:5,send:[0,14,15,16],snag:[14,16],getargspec:9,sent:[15,4,16,3],deactiv:16,rollback:9,splitresult:4,"h\u00f8gsbro":3,nabriski:3,chdir:[15,13],facebook:13,b14b9a:3,relev:4,recip:[1,5,16],notabl:4,button:0,michael:3,"try":[14,12,16,9],evt:14,pleas:[0,1,2,3,15,9,16],bottlepi:[0,16,3],impli:1,smaller:4,natur:14,crop:5,focu:15,video:5,virtaulli:9,download:[0,1,2,10,3,16],somewsgiappl:5,click:0,append:4,compat:[0,9,13,3],index:[10,1,5,3,4,12],compar:14,anton:3,m35:3,cell:15,progess:15,whatev:[15,16,9],pagenam:16,len:16,closur:9,logout:5,ubuntu:16,vukel:3,becom:[15,16,13],sinc:[10,14,16,3],convert:[15,12,16],mailinglist:[0,11],copyright:1,artifici:15,larger:[10,15],file_wrapp:16,chang:[0,10,3,5,9,4,12,13,15,16],chanc:16,danger:16,appli:[0,3,15,9,4,16],app:[1,2,3,5,6,7,9,10,4,12,13,14,16],gatewai:4,apt:[0,16],api:[0,1,3,15,8,9,4,13,14,16],regexp:[12,16],redi:7,cloud:5,from:[0,1,2,3,5,8,9,10,4,13,14,15,16],zip:0,commun:[0,14,13],doubl:[15,2,8,3],next:[0,3,15,6,9,4,12,14,16],websit:[15,11],few:[14,15],sort:[15,3],proxypass:13,benchmark:14,trail:[1,5],name2:16,rare:[0,9,16,3],alexei:3,account:[0,16],alik:16,retriev:[15,16],alia:4,alic:16,annoi:8,thin:16,meet:16,fetch:[0,14,5,4,16],aliv:[1,5],control:[3,5,9,4,12,13,16],sqlite:[10,15,7,16,9],quickstart:[1,5,16],tar:0,process:[15,9,4,13,14,16],lock:13,sudo:[0,16],high:[14,16,13],tag:[0,15],delai:16,filepath:[6,16],data_dir:5,narr:4,brian:3,subdirectori:16,instead:[0,3,15,6,8,9,4,13,14,16],overridden:16,stop:[14,15,8,16,12],xc3:16,geventwebsocket:14,debugger_class:2,bind:[14,15,4,16],counter:[5,16],correspond:[0,1,15,16,14],element:12,issu:[0,16,9],returend:4,allow:[0,1,2,3,5,6,8,4,12,13,14,15,16],fallback:16,furnish:1,move:[14,15,4],comma:[8,12],tort:1,werkzueg:2,georg:11,therefor:9,crash:[5,16],dal:7,auto:[3,5,4,13,15,16],databs:15,handi:16,auth:[4,16,3],onmessag:14,mention:[0,16],automat:[10,3,15,8,9,4,13,16],front:[5,4,8],align:8,anyth:[0,15,4,16,9],edit:[0,15,12,16],debuggingmiddlewar:5,nameerror:8,mode:[5,4,16,3],chunk:[14,16],getlist:4,new_id:15,meta:[4,7,16,9],"static":[3,5,7,9,12,13,15,16],our:[0,15,16],explicit:[1,12,16],special:[14,4,8,16,3],out:[1,5,6,8,11,4,13],variabl:[15,4,8,16,3],twice:16,req:2,texliv:0,suitabl:[15,6],rel:[14,4,16,13],enable_cor:5,dbfile:[10,16,9],insid:15,workflow:[0,1],kontaktaufnahm:11,frank:3,manipul:[4,16],undo:0,dictionari:[3,5,9,4,15,16],releas:[0,1,16,3],my_todo_list:15,greedi:[12,16],indent:[8,16],unwant:9,could:[5,16],learning_python:16,david:3,length:[4,16],outsid:13,waitress:[13,3],cookie_expir:5,softwar:[1,15,10],delete_cooki:4,date:0,owner:4,contextloc:16,prioriti:16,"long":[0,15,8,9,4,14,16],unknown:4,licens:1,perfectli:[15,16,13],system:[10,5,15,16],wrapper:[4,2,9],attach:[4,16,13],attack:[8,16],request_class:2,physic:13,termin:[14,4,16],"final":[1,3,15,9,14,16],gotcha:16,shallow:4,insbesonder:11,exactli:[14,15,4,16],bei:11,bother:15,bottle_sqlit:16,requesthandl:14,structur:[0,1,4,16,3],charact:[3,15,8,4,12,16],sens:15,exp:12,heuss:11,kellei:3,have:[0,1,2,3,5,6,7,8,9,10,4,13,14,15,16],tabl:15,need:[0,10,3,5,9,12,13,14,15,16],itamar:3,turn:[5,4,16],border:15,optimis:16,mako_view:4,rout:[3,10,2,1,5,6,9,4,12,14,15,16],pluginerror:9,mix:[14,15,4],my_bugfix:0,which:[0,2,5,9,4,12,14,15,16],mit:[1,11],singl:[1,3,15,8,9,4,13,16],uppercas:4,rfc3986:5,deploy:[1,16,13],borzenkov:3,who:3,callabl:[8,9,4,12,13,14,16],segment:[4,12,16],payment:4,latin1:[4,16],url:[0,1,3,5,6,9,4,12,13,14,15,16],request:[0,1,2,3,5,6,7,9,10,4,12,13,14,15,16],uri:4,deni:[15,16,13],snapshot:16,determin:12,skiplist:[4,9],fact:[0,8,12],text:[14,15,4,8,16],verbos:[16,3],bring:15,server_nam:[4,13],fear:9,input_encod:4,trivial:0,anywai:[0,5,15,13],redirect:[4,6,16,3],textual:16,locat:[6,16,3],your_github_account:0,should:[0,3,5,6,9,4,12,13,14,15,16],won:[15,6,8,16,9],suppos:15,add_filt:12,local:[0,10,2,6,8,9,4,13,16],hope:3,footer_templ:8,pypa:16,contribut:[0,1],pypi:[0,1,16],autom:[16,13],autor:11,increas:[0,16,13],milbi:3,lossless:4,httperror:[10,3,5,9,4,16],enabl:[15,2,16,9],approach:16,stuff:0,integr:[0,7,2,16],contain:[0,10,15,8,9,4,12,16],grab:[15,16],view:[4,15,6,8,16],conform:[14,9,4,13],legaci:[1,12],smooth:3,frame:8,knowledg:[1,15],accord:1,multipart:[5,4,16],mileston:0,statu:[5,4,15,16,3],wire:16,correctli:[4,16],edit_task:15,favor:9,state:[10,15,13],neither:[4,16],email:[0,16],verifi:4,kei:[2,3,15,8,4,5,16],apheag:3,entir:[0,16],gilmor:3,exclam:8,addit:[10,3,15,8,9,4,16],plugin:[10,2,1,5,3,7,9,4,16],admin:[9,5,4,13],equal:[4,9,6,12,3],someasyncwork:14,etc:[15,16],instanc:[10,2,3,9,4,12,13,16],sigterm:16,comment:[0,8],venv:0,rfc2617:4,arriv:12,distinguish:12,rpc:6,template_path:[6,16],quit:[15,16,9],silvio:3,platform:5,fix_environ_middlewar:6,sqliteplugin:[1,16,9],json:[15,4,16,3],treat:[5,16],immedi:[4,8,16,9],catchal:[5,4,16],soulier:3,assert:[5,16],decim:[12,16],togeth:[12,16],present:[0,3,15,8,9,4,16],multi:[15,8,9,4,13,14,16],plain:[15,4,16],fapwsserv:15,cursor:15,defin:[3,5,8,9,4,12,14,15,16],item_:15,rightblock:8,glossari:[1,16],fullpath:4,werb:11,layer:16,helper:[8,16,13],almost:[0,14],site:[0,14,5],path_shift:4,roll:10,archiv:0,duan:3,substanti:1,lightweight:1,revis:[0,15],scienc:11,simpletaltempl:3,let:[0,5,8,9,4,13,14,15,16],welcom:16,parti:[7,16],cross:[5,16],python:[0,1,2,3,4,5,8,10,11,12,13,14,15,16],httperf:14,multidict:[4,16,3],fetchon:[10,15,16,9],difficult:8,http:[0,1,5,6,9,4,13,14,15,16],hostnam:4,show_item:15,maxlength:15,upon:[5,7],effect:[14,15,16,9],column_nam:9,expand:3,default_app:[3,15,6,4,13,16],nevertheless:15,keyboardinterrupt:16,myclust:13,well:[14,15,4,16,13],theodor:11,set_cooki:[4,16,3],exampl:[0,1,2,5,6,8,9,4,12,13,14,15,16],command:[10,15,2,16,3],choos:[15,9,12,13],undefin:[8,3],piec:[15,16],usual:[15,8,9,4,5,16],test2:16,newest:[4,16],rocket:13,less:[14,16,9],obtain:1,static_fil:[15,9,16,3],web:[0,1,5,6,7,4,13,14,15,16],jinja:4,jeff:3,smith:[16,3],getal:[4,16],add:[0,10,2,3,5,6,7,8,9,4,12,13,14,15,16],listenhttp:13,buxton:3,lookup:[4,8,13],smart:16,branch:0,webseit:11,howto:1,show_json:15,cedar:5,know:[0,15,6,9,12,14],password:[15,4,16],recurs:9,mypag:15,xss:[8,16],like:[10,5,6,9,4,13,14,15,16],success:[15,16],incred:[14,16],necessari:15,async:5,page:[0,10,2,5,8,9,4,12,14,15,16],apexi200sx:3,revers:[4,6,16,13],twitter:[0,11],gevent:[14,5,13,3],flush:16,proper:[5,15],guarante:0,librari:[10,2,1,5,7,8,4,13,14,15,16],tmp:[10,16,9],guid:[0,1,3,5,7,9,16],lead:[4,8],avoid:[0,3,9,4,12,14,16],overlap:12,jeremi:3,speak:14,murdock:3,usag:[1,2,10,7,8,9,14,16],symlink:4,host:[0,1,5,6,4,13,14,15,16],obei:2,although:[15,6],simplet:3,stage:16,beaker:5,get_iso:16,about:[0,1,15,6,7,8,9,11,14,16],actual:[0,15,9,4,13,14],socket:[14,16],column:[15,8,9],disabl:[8,16,9],own:[0,15,4,12,13,5,16],easy_instal:[1,15,2,16,10],get_latin:16,warranti:1,pitfal:[1,6],merg:[0,1,4,16,3],before_callback:5,mod_python:6,new_item:15,trigger:[0,10,4,16],request_environ:4,"var":[14,15,4,13],"function":[1,3,5,7,8,9,4,12,13,14,15,16],check_user_credenti:16,brand:3,subscrib:0,alexi:3,bodi:[3,8,9,4,14,16],gain:15,uninstal:[4,16,9],display_forum:16,eas:16,inlin:8,bug:[0,1,3,15,8,9],count:16,made:[15,9,16,3],whether:[1,15,10],resourcemanag:[4,3],writeabl:4,displai:16,asynchron:[1,5,14,13],below:[5,9,4,13,15,16],limit:[1,9,4,13,14,16],otherwis:[1,15,4,8,12],problem:[1,9,6,16,14],evalu:[2,16],"int":[15,5,12,16,3],dure:[5,4,15,16],twist:[14,13],problemen:11,implement:[0,2,3,5,7,8,9,4,12,14,16],pip:[0,10,2,16],probabl:[0,14,16,9],vorgesehen:11,"2to3":3,detail:[3,5,9,4,12,14,15,16],virtual:[14,15,16,13],other:[0,1,3,5,6,7,8,9,4,12,15,16],bool:15,futur:[0,3,9,4,12,16],rememb:15,user_api:16,servernam:[15,13],"class":[10,2,1,5,3,8,9,4,14,16],debian:16,stai:[0,6,12],sphinx:[0,16],rule:[0,1,9,4,12,16],gsite:11,portion:[1,4],show_post:16,understand:[15,12,13]},objtypes:{"0":"py:module","1":"py:function","2":"py:method","3":"py:attribute","4":"py:class","5":"py:data","6":"py:exception","7":"py:classmethod"},titles:["Developer Notes","Bottle: Python Web Framework","Bottle-Werkzeug","Release Notes and Changelog","API Reference","Recipes","Frequently Asked Questions","List of available Plugins","SimpleTemplate Engine","Plugin Development Guide","Bottle-SQLite","Contact","Request Routing","Deployment","Primer to Asynchronous Applications","Tutorial: Todo-List Application","Tutorial"],objnames:{"0":["py","module","Python module"],"1":["py","function","Python function"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","class","Python class"],"5":["py","data","Python data"],"6":["py","exception","Python exception"],"7":["py","classmethod","Python class method"]},filenames:["development","index","plugins/werkzeug","changelog","api","recipes","faq","plugins/index","stpl","plugindev","plugins/sqlite","contact","routing","deployment","async","tutorial_app","tutorial"]})
\ No newline at end of file
diff --git a/html/stpl.html b/html/stpl.html
new file mode 100644 (file)
index 0000000..9b683e6
--- /dev/null
@@ -0,0 +1,427 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>SimpleTemplate Engine &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="API Reference" href="api.html" />
+    <link rel="prev" title="Request Routing" href="routing.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="api.html" title="API Reference"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="routing.html" title="Request Routing"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="simpletemplate-engine">
+<h1>SimpleTemplate Engine<a class="headerlink" href="#simpletemplate-engine" title="Permalink to this headline">¶</a></h1>
+<p>Bottle comes with a fast, powerful and easy to learn built-in template engine called <em>SimpleTemplate</em> or <em>stpl</em> for short. It is the default engine used by the <a class="reference internal" href="api.html#bottle.view" title="bottle.view"><tt class="xref py py-func docutils literal"><span class="pre">view()</span></tt></a> and <a class="reference internal" href="api.html#bottle.template" title="bottle.template"><tt class="xref py py-func docutils literal"><span class="pre">template()</span></tt></a> helpers but can be used as a stand-alone general purpose template engine too. This document explains the template syntax and shows examples for common use cases.</p>
+<p class="rubric">Basic API Usage:</p>
+<p><a class="reference internal" href="#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> implements the <a class="reference internal" href="api.html#bottle.BaseTemplate" title="bottle.BaseTemplate"><tt class="xref py py-class docutils literal"><span class="pre">BaseTemplate</span></tt></a> API:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">SimpleTemplate</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">tpl</span> <span class="o">=</span> <span class="n">SimpleTemplate</span><span class="p">(</span><span class="s">&#39;Hello {{name}}!&#39;</span><span class="p">)</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">tpl</span><span class="o">.</span><span class="n">render</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;World&#39;</span><span class="p">)</span>
+<span class="go">u&#39;Hello World!&#39;</span>
+</pre></div>
+</div>
+<p>In this document we use the <a class="reference internal" href="api.html#bottle.template" title="bottle.template"><tt class="xref py py-func docutils literal"><span class="pre">template()</span></tt></a> helper in examples for the sake of simplicity:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">template</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{name}}!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;World&#39;</span><span class="p">)</span>
+<span class="go">u&#39;Hello World!&#39;</span>
+</pre></div>
+</div>
+<p>Just keep in mind that compiling and rendering templates are two different actions, even if the <a class="reference internal" href="api.html#bottle.template" title="bottle.template"><tt class="xref py py-func docutils literal"><span class="pre">template()</span></tt></a> helper hides this fact. Templates are usually compiled only once and cached internally, but rendered many times with different keyword arguments.</p>
+<div class="section" id="simpletemplate-syntax">
+<h2><a class="reference internal" href="#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> Syntax<a class="headerlink" href="#simpletemplate-syntax" title="Permalink to this headline">¶</a></h2>
+<p>Python is a very powerful language but its whitespace-aware syntax makes it difficult to use as a template language. SimpleTemplate removes some of these restrictions and allows you to write clean, readable and maintainable templates while preserving full access to the features, libraries and speed of the Python language.</p>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">The <a class="reference internal" href="#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> syntax compiles directly to python bytecode and is executed on each <a class="reference internal" href="#bottle.SimpleTemplate.render" title="bottle.SimpleTemplate.render"><tt class="xref py py-meth docutils literal"><span class="pre">SimpleTemplate.render()</span></tt></a> call. Do not render untrusted templates! They may contain and execute harmful python code.</p>
+</div>
+<div class="section" id="inline-expressions">
+<h3>Inline Expressions<a class="headerlink" href="#inline-expressions" title="Permalink to this headline">¶</a></h3>
+<p>You already learned the use of the <tt class="docutils literal"><span class="pre">{{...}}</span></tt> syntax from the &#8220;Hello World!&#8221; example above, but there is more: any python expression is allowed within the curly brackets as long as it returns a string or something that has a string representation:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{name}}!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;World&#39;</span><span class="p">)</span>
+<span class="go">u&#39;Hello World!&#39;</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{name.title() if name else &quot;stranger&quot;}}!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
+<span class="go">u&#39;Hello stranger!&#39;</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{name.title() if name else &quot;stranger&quot;}}!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;mArC&#39;</span><span class="p">)</span>
+<span class="go">u&#39;Hello Marc!&#39;</span>
+</pre></div>
+</div>
+<p>The contained python expression is executed at render-time and has access to all keyword arguments passed to the <a class="reference internal" href="#bottle.SimpleTemplate.render" title="bottle.SimpleTemplate.render"><tt class="xref py py-meth docutils literal"><span class="pre">SimpleTemplate.render()</span></tt></a> method. HTML special characters are escaped automatically to prevent <a class="reference external" href="http://en.wikipedia.org/wiki/Cross-Site_Scripting">XSS</a> attacks. You can start the expression with an exclamation mark to disable escaping for that expression:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{name}}!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;&lt;b&gt;World&lt;/b&gt;&#39;</span><span class="p">)</span>
+<span class="go">u&#39;Hello &amp;lt;b&amp;gt;World&amp;lt;/b&amp;gt;!&#39;</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{!name}}!&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;&lt;b&gt;World&lt;/b&gt;&#39;</span><span class="p">)</span>
+<span class="go">u&#39;Hello &lt;b&gt;World&lt;/b&gt;!&#39;</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="embedded-python-code">
+<h3>Embedded python code<a class="headerlink" href="#embedded-python-code" title="Permalink to this headline">¶</a></h3>
+<p>The <tt class="docutils literal"><span class="pre">%</span></tt> character marks a line of python code. The only difference between this and real python code is that you have to explicitly close blocks with an <tt class="docutils literal"><span class="pre">%end</span></tt> statement. In return you can align the code with the surrounding template and don&#8217;t have to worry about correct indentation of blocks. The <em>SimpleTemplate</em> parser handles that for you. Lines <em>not</em> starting with a <tt class="docutils literal"><span class="pre">%</span></tt> are rendered as text as usual:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>%if name:
+  Hi <span class="nt">&lt;b&gt;</span><span class="cp">{{</span><span class="nv">name</span><span class="cp">}}</span><span class="nt">&lt;/b&gt;</span>
+%else:
+  <span class="nt">&lt;i&gt;</span>Hello stranger<span class="nt">&lt;/i&gt;</span>
+%end
+</pre></div>
+</div>
+<p>The <tt class="docutils literal"><span class="pre">%</span></tt> character is only recognised if it is the first non-whitespace character in a line. To escape a leading <tt class="docutils literal"><span class="pre">%</span></tt> you can add a second one. <tt class="docutils literal"><span class="pre">%%</span></tt> is replaced by a single <tt class="docutils literal"><span class="pre">%</span></tt> in the resulting template:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>This line contains a % but no python code.
+%% This text-line starts with &#39;%&#39;
+%%% This text-line starts with &#39;%%&#39;
+</pre></div>
+</div>
+</div>
+<div class="section" id="suppressing-line-breaks">
+<h3>Suppressing line breaks<a class="headerlink" href="#suppressing-line-breaks" title="Permalink to this headline">¶</a></h3>
+<p>You can suppress the line break in front of a code-line by adding a double backslash at the end of the line:</p>
+<div class="highlight-html+django"><div class="highlight"><pre><span class="nt">&lt;span&gt;</span>\\
+%if True:
+nobreak\\
+%end
+<span class="nt">&lt;/span&gt;</span>
+</pre></div>
+</div>
+<p>This template produces the following output:</p>
+<div class="highlight-html+django"><div class="highlight"><pre><span class="nt">&lt;span&gt;</span>nobreak<span class="nt">&lt;/span&gt;</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="the-include-statement">
+<h3>The <tt class="docutils literal"><span class="pre">%include</span></tt> Statement<a class="headerlink" href="#the-include-statement" title="Permalink to this headline">¶</a></h3>
+<p>You can include other templates using the <tt class="docutils literal"><span class="pre">%include</span> <span class="pre">sub_template</span> <span class="pre">[kwargs]</span></tt> statement. The <tt class="docutils literal"><span class="pre">sub_template</span></tt> parameter specifies the name or path of the template to be included. The rest of the line is interpreted as a comma-separated list of <tt class="docutils literal"><span class="pre">key=statement</span></tt> pairs similar to keyword arguments in function calls. They are passed to the sub-template analogous to a <a class="reference internal" href="#bottle.SimpleTemplate.render" title="bottle.SimpleTemplate.render"><tt class="xref py py-meth docutils literal"><span class="pre">SimpleTemplate.render()</span></tt></a> call. The <tt class="docutils literal"><span class="pre">**kwargs</span></tt> syntax for passing a dict is allowed too:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>%include header_template title=&#39;Hello World&#39;
+<span class="nt">&lt;p&gt;</span>Hello World<span class="nt">&lt;/p&gt;</span>
+%include footer_template
+</pre></div>
+</div>
+</div>
+<div class="section" id="the-rebase-statement">
+<h3>The <tt class="docutils literal"><span class="pre">%rebase</span></tt> Statement<a class="headerlink" href="#the-rebase-statement" title="Permalink to this headline">¶</a></h3>
+<p>The <tt class="docutils literal"><span class="pre">%rebase</span> <span class="pre">base_template</span> <span class="pre">[kwargs]</span></tt> statement causes <tt class="docutils literal"><span class="pre">base_template</span></tt> to be rendered instead of the original template. The base-template then includes the original template using an empty <tt class="docutils literal"><span class="pre">%include</span></tt> statement and has access to all variables specified by <tt class="docutils literal"><span class="pre">kwargs</span></tt>. This way it is possible to wrap a template with another template or to simulate the inheritance feature found in some other template engines.</p>
+<p>Let&#8217;s say you have a content template and want to wrap it with a common HTML layout frame. Instead of including several header and footer templates, you can use a single base-template to render the layout frame.</p>
+<p>Base-template named <tt class="docutils literal"><span class="pre">layout.tpl</span></tt>:</p>
+<div class="highlight-html+django"><div class="highlight"><pre><span class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;head&gt;</span>
+  <span class="nt">&lt;title&gt;</span><span class="cp">{{</span><span class="nv">title</span> <span class="k">or</span> <span class="s1">&#39;No title&#39;</span><span class="cp">}}</span><span class="nt">&lt;/title&gt;</span>
+<span class="nt">&lt;/head&gt;</span>
+<span class="nt">&lt;body&gt;</span>
+  %include
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+</pre></div>
+</div>
+<p>Main-template named <tt class="docutils literal"><span class="pre">content.tpl</span></tt>:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>This is the page content: <span class="cp">{{</span><span class="nv">content</span><span class="cp">}}</span>
+%rebase layout title=&#39;Content Title&#39;
+</pre></div>
+</div>
+<p>Now you can render <tt class="docutils literal"><span class="pre">content.tpl</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;content&#39;</span><span class="p">,</span> <span class="n">content</span><span class="o">=</span><span class="s">&#39;Hello World!&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<div class="highlight-html"><div class="highlight"><pre><span class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;head&gt;</span>
+  <span class="nt">&lt;title&gt;</span>Content Title<span class="nt">&lt;/title&gt;</span>
+<span class="nt">&lt;/head&gt;</span>
+<span class="nt">&lt;body&gt;</span>
+  This is the page content: Hello World!
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+</pre></div>
+</div>
+<p>A more complex scenario involves chained rebases and multiple content blocks. The <tt class="docutils literal"><span class="pre">block_content.tpl</span></tt> template defines two functions and passes them to a <tt class="docutils literal"><span class="pre">columns.tpl</span></tt> base template:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>%def leftblock():
+  Left block content.
+%end
+%def rightblock():
+  Right block content.
+%end
+%rebase columns leftblock=leftblock, rightblock=rightblock, title=title
+</pre></div>
+</div>
+<p>The <tt class="docutils literal"><span class="pre">columns.tpl</span></tt> base-template uses the two callables to render the content of the left and right column. It then wraps itself with the <tt class="docutils literal"><span class="pre">layout.tpl</span></tt> template defined earlier:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>%rebase layout title=title
+<span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&quot;width: 50%; float:left&quot;</span><span class="nt">&gt;</span>
+  %leftblock()
+<span class="nt">&lt;/div&gt;</span>
+<span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&quot;width: 50%; float:right&quot;</span><span class="nt">&gt;</span>
+  %rightblock()
+<span class="nt">&lt;/div&gt;</span>
+</pre></div>
+</div>
+<p>Lets see how <tt class="docutils literal"><span class="pre">block_content.tpl</span></tt> renders:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;block_content&#39;</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s">&#39;Hello World!&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<div class="highlight-html"><div class="highlight"><pre><span class="nt">&lt;html&gt;</span>
+<span class="nt">&lt;head&gt;</span>
+  <span class="nt">&lt;title&gt;</span>Hello World<span class="nt">&lt;/title&gt;</span>
+<span class="nt">&lt;/head&gt;</span>
+<span class="nt">&lt;body&gt;</span>
+<span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&quot;width: 50%; float:left&quot;</span><span class="nt">&gt;</span>
+  Left block content.
+<span class="nt">&lt;/div&gt;</span>
+<span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">&quot;width: 50%; float:right&quot;</span><span class="nt">&gt;</span>
+  Right block content.
+<span class="nt">&lt;/div&gt;</span>
+<span class="nt">&lt;/body&gt;</span>
+<span class="nt">&lt;/html&gt;</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="namespace-functions">
+<h3>Namespace Functions<a class="headerlink" href="#namespace-functions" title="Permalink to this headline">¶</a></h3>
+<p>Accessing undefined variables in a template raises <tt class="xref py py-exc docutils literal"><span class="pre">NameError</span></tt> and
+stops rendering immediately. This is standard python behavior and nothing new,
+but vanilla python lacks an easy way to check the availability of a variable.
+This quickly gets annoying if you want to support flexible inputs or use the
+same template in different situations. SimpleTemplate helps you out here: The
+following three functions are defined in the default namespace and accessible
+from anywhere within a template:</p>
+<dl class="function">
+<dt id="stpl.defined">
+<tt class="descname">defined</tt><big>(</big><em>name</em><big>)</big><a class="headerlink" href="#stpl.defined" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return True if the variable is defined in the current template namespace,
+False otherwise.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="stpl.get">
+<tt class="descname">get</tt><big>(</big><em>name</em>, <em>default=None</em><big>)</big><a class="headerlink" href="#stpl.get" title="Permalink to this definition">¶</a></dt>
+<dd><p>Return the variable, or a default value.</p>
+</dd></dl>
+
+<dl class="function">
+<dt id="stpl.setdefault">
+<tt class="descname">setdefault</tt><big>(</big><em>name</em>, <em>default</em><big>)</big><a class="headerlink" href="#stpl.setdefault" title="Permalink to this definition">¶</a></dt>
+<dd><p>If the variable is not defined, create it with the given default value.
+Return the variable.</p>
+</dd></dl>
+
+<p>Here is an example that uses all three functions to implement optional template
+variables in different ways:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>% setdefault(&#39;text&#39;, &#39;No Text&#39;)
+<span class="nt">&lt;h1&gt;</span><span class="cp">{{</span><span class="nv">get</span><span class="o">(</span><span class="s1">&#39;title&#39;</span><span class="o">,</span> <span class="s1">&#39;No Title&#39;</span><span class="o">)</span><span class="cp">}}</span><span class="nt">&lt;/h1&gt;</span>
+<span class="nt">&lt;p&gt;</span> <span class="cp">{{</span> <span class="nv">text</span> <span class="cp">}}</span> <span class="nt">&lt;/p&gt;</span>
+% if defined(&#39;author&#39;):
+  <span class="nt">&lt;p&gt;</span>By <span class="cp">{{</span> <span class="nv">author</span> <span class="cp">}}</span><span class="nt">&lt;/p&gt;</span>
+% end
+</pre></div>
+</div>
+</div>
+</div>
+<div class="section" id="simpletemplate-api">
+<h2><a class="reference internal" href="#bottle.SimpleTemplate" title="bottle.SimpleTemplate"><tt class="xref py py-class docutils literal"><span class="pre">SimpleTemplate</span></tt></a> API<a class="headerlink" href="#simpletemplate-api" title="Permalink to this headline">¶</a></h2>
+<dl class="class">
+<dt id="bottle.SimpleTemplate">
+<em class="property">class </em><tt class="descname">SimpleTemplate</tt><big>(</big><em>source=None</em>, <em>name=None</em>, <em>lookup=</em><span class="optional">[</span><span class="optional">]</span>, <em>encoding='utf8'</em>, <em>**settings</em><big>)</big><a class="reference internal" href="_modules/bottle.html#SimpleTemplate"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.SimpleTemplate" title="Permalink to this definition">¶</a></dt>
+<dd><dl class="classmethod">
+<dt id="bottle.SimpleTemplate.split_comment">
+<em class="property">classmethod </em><tt class="descname">split_comment</tt><big>(</big><em>code</em><big>)</big><a class="reference internal" href="_modules/bottle.html#SimpleTemplate.split_comment"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.SimpleTemplate.split_comment" title="Permalink to this definition">¶</a></dt>
+<dd><p>Removes comments (#...) from python code.</p>
+</dd></dl>
+
+<dl class="method">
+<dt id="bottle.SimpleTemplate.render">
+<tt class="descname">render</tt><big>(</big><em>*args</em>, <em>**kwargs</em><big>)</big><a class="reference internal" href="_modules/bottle.html#SimpleTemplate.render"><span class="viewcode-link">[source]</span></a><a class="headerlink" href="#bottle.SimpleTemplate.render" title="Permalink to this definition">¶</a></dt>
+<dd><p>Render the template using keyword arguments as local variables.</p>
+</dd></dl>
+
+</dd></dl>
+
+</div>
+<div class="section" id="known-bugs">
+<h2>Known bugs<a class="headerlink" href="#known-bugs" title="Permalink to this headline">¶</a></h2>
+<p>Some syntax constructions allowed in python are problematic within a template. The following syntaxes won&#8217;t work with SimpleTemplate:</p>
+<blockquote>
+<div><ul class="simple">
+<li>Multi-line statements must end with a backslash (<tt class="docutils literal"><span class="pre">\</span></tt>) and a comment, if present, must not contain any additional <tt class="docutils literal"><span class="pre">#</span></tt> characters.</li>
+<li>Multi-line strings are not supported yet.</li>
+</ul>
+</div></blockquote>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">SimpleTemplate Engine</a><ul>
+<li><a class="reference internal" href="#simpletemplate-syntax"><tt class="docutils literal"><span class="pre">SimpleTemplate</span></tt> Syntax</a><ul>
+<li><a class="reference internal" href="#inline-expressions">Inline Expressions</a></li>
+<li><a class="reference internal" href="#embedded-python-code">Embedded python code</a></li>
+<li><a class="reference internal" href="#suppressing-line-breaks">Suppressing line breaks</a></li>
+<li><a class="reference internal" href="#the-include-statement">The <tt class="docutils literal"><span class="pre">%include</span></tt> Statement</a></li>
+<li><a class="reference internal" href="#the-rebase-statement">The <tt class="docutils literal"><span class="pre">%rebase</span></tt> Statement</a></li>
+<li><a class="reference internal" href="#namespace-functions">Namespace Functions</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#simpletemplate-api"><tt class="docutils literal"><span class="pre">SimpleTemplate</span></tt> API</a></li>
+<li><a class="reference internal" href="#known-bugs">Known bugs</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="routing.html"
+                        title="previous chapter">Request Routing</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="api.html"
+                        title="next chapter">API Reference</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/stpl.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="api.html" title="API Reference"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="routing.html" title="Request Routing"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_stpl';
+      var disqus_title = 'SimpleTemplate Engine';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/tutorial.html b/html/tutorial.html
new file mode 100644 (file)
index 0000000..dc3207f
--- /dev/null
@@ -0,0 +1,988 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Tutorial &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Request Routing" href="routing.html" />
+    <link rel="prev" title="Bottle: Python Web Framework" href="index.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="routing.html" title="Request Routing"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="index.html" title="Bottle: Python Web Framework"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <span class="target" id="module-bottle"></span><div class="section" id="tutorial">
+<h1>Tutorial<a class="headerlink" href="#tutorial" title="Permalink to this headline">¶</a></h1>
+<p>This tutorial introduces you to the concepts and features of the Bottle web framework and covers basic and advanced topics alike. You can read it from start to end, or use it as a reference later on. The automatically generated <a class="reference internal" href="api.html"><em>API Reference</em></a> may be interesting for you, too. It covers more details, but explains less than this tutorial. Solutions for the most common questions can be found in our <a class="reference internal" href="recipes.html"><em>Recipes</em></a> collection or on the <a class="reference internal" href="faq.html"><em>Frequently Asked Questions</em></a> page. If you need any help, join our <a class="reference external" href="mailto:bottlepy&#37;&#52;&#48;googlegroups&#46;com">mailing list</a> or visit us in our <a class="reference external" href="http://webchat.freenode.net/?channels=bottlepy">IRC channel</a>.</p>
+<div class="section" id="installation">
+<span id="id1"></span><h2>Installation<a class="headerlink" href="#installation" title="Permalink to this headline">¶</a></h2>
+<p>Bottle does not depend on any external libraries. You can just download <a class="reference external" href="/bottle.py">bottle.py</a> into your project directory and start coding:</p>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>wget http://bottlepy.org/bottle.py
+</pre></div>
+</div>
+<p>This will get you the latest development snapshot that includes all the new features. If you prefer a more stable environment, you should stick with the stable releases. These are available on <a class="reference external" href="http://pypi.python.org/pypi/bottle">PyPi</a> and can be installed via <strong class="command">pip</strong> (recommended), <strong class="command">easy_install</strong> or your package manager:</p>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>sudo pip install bottle              <span class="c"># recommended</span>
+<span class="nv">$ </span>sudo easy_install bottle             <span class="c"># alternative without pip</span>
+<span class="nv">$ </span>sudo apt-get install python-bottle   <span class="c"># works for debian, ubuntu, ...</span>
+</pre></div>
+</div>
+<p>Either way, you&#8217;ll need Python 2.5 or newer (including 3.x) to run bottle applications. If you do not have permissions to install packages system-wide or simply don&#8217;t want to, create a <a class="reference external" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a> first:</p>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>virtualenv develop              <span class="c"># Create virtual environment</span>
+<span class="nv">$ </span><span class="nb">source </span>develop/bin/activate     <span class="c"># Change default python to virtual one</span>
+<span class="o">(</span>develop<span class="o">)</span><span class="nv">$ </span>pip install -U bottle  <span class="c"># Install bottle to virtual environment</span>
+</pre></div>
+</div>
+<p>Or, if virtualenv is not installed on your system:</p>
+<div class="highlight-bash"><div class="highlight"><pre><span class="nv">$ </span>wget https://raw.github.com/pypa/virtualenv/master/virtualenv.py
+<span class="nv">$ </span>python virtualenv.py develop    <span class="c"># Create virtual environment</span>
+<span class="nv">$ </span><span class="nb">source </span>develop/bin/activate     <span class="c"># Change default python to virtual one</span>
+<span class="o">(</span>develop<span class="o">)</span><span class="nv">$ </span>pip install -U bottle  <span class="c"># Install bottle to virtual environment</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="quickstart-hello-world">
+<h2>Quickstart: &#8220;Hello World&#8221;<a class="headerlink" href="#quickstart-hello-world" title="Permalink to this headline">¶</a></h2>
+<p>This tutorial assumes you have Bottle either <a class="reference internal" href="#installation"><em>installed</em></a> or copied into your project directory. Let&#8217;s start with a very basic &#8220;Hello World&#8221; example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&quot;Hello World!&quot;</span>
+
+<span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This is it. Run this script, visit <a class="reference external" href="http://localhost:8080/hello">http://localhost:8080/hello</a> and you will see &#8220;Hello World!&#8221; in your browser. Here is how it works:</p>
+<p>The <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator binds a piece of code to an URL path. In this case, we link the <tt class="docutils literal"><span class="pre">/hello</span></tt> URL to the <tt class="docutils literal"><span class="pre">hello()</span></tt> function. This is called a <cite>route</cite> (hence the decorator name) and is the most important concept of this framework. You can define as many routes as you want. Whenever a browser requests an URL, the associated function is called and the return value is sent back to the browser. Its as simple as that.</p>
+<p>The <a class="reference internal" href="api.html#bottle.run" title="bottle.run"><tt class="xref py py-func docutils literal"><span class="pre">run()</span></tt></a> call in the last line starts a built-in development server. It runs on <cite>localhost</cite> port 8080 and serves requests until you hit <tt class="kbd docutils literal"><span class="pre">Control-c</span></tt>. You can switch the server backend later, but for now a development server is all we need. It requires no setup at all and is an incredibly painless way to get your application up and running for local tests.</p>
+<p>The <a class="reference internal" href="#tutorial-debugging"><em>Debug Mode</em></a> is very helpful during early development, but should be switched off for public applications. Keep that in mind.</p>
+<p>Of course this is a very simple example, but it shows the basic concept of how applications are built with Bottle. Continue reading and you&#8217;ll see what else is possible.</p>
+<div class="section" id="the-default-application">
+<span id="tutorial-default"></span><h3>The <cite>Default Application</cite><a class="headerlink" href="#the-default-application" title="Permalink to this headline">¶</a></h3>
+<p>For the sake of simplicity, most examples in this tutorial use a module-level <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator to define routes. This adds routes to a global &#8220;default application&#8221;, an instance of <a class="reference internal" href="api.html#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> that is automatically created the first time you call <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a>. Several other module-level decorators and functions relate to this default application, but if you prefer a more object oriented approach and don&#8217;t mind the extra typing, you can create a separate application object and use that instead of the global one:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">Bottle</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">template</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&quot;Hello World!&quot;</span>
+
+<span class="n">run</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8080</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>The object-oriented approach is further described in the <a class="reference internal" href="#default-app"><em>Default Application</em></a> section. Just keep in mind that you have a choice.</p>
+</div>
+</div>
+<div class="section" id="request-routing">
+<span id="tutorial-routing"></span><h2>Request Routing<a class="headerlink" href="#request-routing" title="Permalink to this headline">¶</a></h2>
+<p>In the last chapter we built a very simple web application with only a single route. Here is the routing part of the &#8220;Hello World&#8221; example again:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&quot;Hello World!&quot;</span>
+</pre></div>
+</div>
+<p>The <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator links an URL path to a callback function, and adds a new route to the <a class="reference internal" href="#tutorial-default"><em>default application</em></a>. An application with just one route is kind of boring, though. Let&#8217;s add some more:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello/&lt;name&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">greet</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;Stranger&#39;</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;Hello {{name}}, how are you?&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This example demonstrates two things: You can bind more than one route to a single callback, and you can add wildcards to URLs and access them via keyword arguments.</p>
+<div class="section" id="dynamic-routes">
+<span id="tutorial-dynamic-routes"></span><h3>Dynamic Routes<a class="headerlink" href="#dynamic-routes" title="Permalink to this headline">¶</a></h3>
+<p>Routes that contain wildcards are called <cite>dynamic routes</cite> (as opposed to <cite>static routes</cite>) and match more than one URL at the same time. A simple wildcard consists of a name enclosed in angle brackets (e.g. <tt class="docutils literal"><span class="pre">&lt;name&gt;</span></tt>) and accepts one or more characters up to the next slash (<tt class="docutils literal"><span class="pre">/</span></tt>). For example, the route <tt class="docutils literal"><span class="pre">/hello/&lt;name&gt;</span></tt> accepts requests for <tt class="docutils literal"><span class="pre">/hello/alice</span></tt> as well as <tt class="docutils literal"><span class="pre">/hello/bob</span></tt>, but not for <tt class="docutils literal"><span class="pre">/hello</span></tt>, <tt class="docutils literal"><span class="pre">/hello/</span></tt> or <tt class="docutils literal"><span class="pre">/hello/mr/smith</span></tt>.</p>
+<p>Each wildcard passes the covered part of the URL as a keyword argument to the request callback. You can use them right away and implement RESTful, nice-looking and meaningful URLs with ease. Here are some other examples along with the URLs they&#8217;d match:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/wiki/&lt;pagename&gt;&#39;</span><span class="p">)</span>            <span class="c"># matches /wiki/Learning_Python</span>
+<span class="k">def</span> <span class="nf">show_wiki_page</span><span class="p">(</span><span class="n">pagename</span><span class="p">):</span>
+    <span class="o">...</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&lt;action&gt;/&lt;user&gt;&#39;</span><span class="p">)</span>            <span class="c"># matches /follow/defnull</span>
+<span class="k">def</span> <span class="nf">user_api</span><span class="p">(</span><span class="n">action</span><span class="p">,</span> <span class="n">user</span><span class="p">):</span>
+    <span class="o">...</span>
+</pre></div>
+</div>
+<p class="versionadded">
+<span class="versionmodified">New in version 0.10.</span></p>
+<p>Filters are used to define more specific wildcards, and/or transform the covered part of the URL before it is passed to the callback. A filtered wildcard is declared as <tt class="docutils literal"><span class="pre">&lt;name:filter&gt;</span></tt> or <tt class="docutils literal"><span class="pre">&lt;name:filter:config&gt;</span></tt>. The syntax for the optional config part depends on the filter used.</p>
+<p>The following filters are implemented by default and more may be added:</p>
+<ul class="simple">
+<li><strong>:int</strong> matches (signed) digits only and converts the value to integer.</li>
+<li><strong>:float</strong> similar to :int but for decimal numbers.</li>
+<li><strong>:path</strong> matches all characters including the slash character in a non-greedy way and can be used to match more than one path segment.</li>
+<li><strong>:re</strong> allows you to specify a custom regular expression in the config field. The matched value is not modified.</li>
+</ul>
+<p>Let&#8217;s have a look at some practical examples:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/object/&lt;id:int&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="nb">id</span><span class="p">):</span>
+    <span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/show/&lt;name:re:[a-z]+&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
+    <span class="k">assert</span> <span class="n">name</span><span class="o">.</span><span class="n">isalpha</span><span class="p">()</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/static/&lt;path:path&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>You can add your own filters as well. See <tt class="xref doc docutils literal"><span class="pre">Routing</span></tt> for details.</p>
+<p class="versionchanged">
+<span class="versionmodified">Changed in version 0.10.</span></p>
+<p>The new rule syntax was introduced in <strong>Bottle 0.10</strong> to simplify some common use cases, but the old syntax still works and you can find a lot of code examples still using it. The differences are best described by example:</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="49%" />
+<col width="51%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Old Syntax</th>
+<th class="head">New Syntax</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td><tt class="docutils literal"><span class="pre">:name</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;name&gt;</span></tt></td>
+</tr>
+<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">:name#regexp#</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;name:re:regexp&gt;</span></tt></td>
+</tr>
+<tr class="row-even"><td><tt class="docutils literal"><span class="pre">:#regexp#</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;:re:regexp&gt;</span></tt></td>
+</tr>
+<tr class="row-odd"><td><tt class="docutils literal"><span class="pre">:##</span></tt></td>
+<td><tt class="docutils literal"><span class="pre">&lt;:re&gt;</span></tt></td>
+</tr>
+</tbody>
+</table>
+<p>Try to avoid the old syntax in future projects if you can. It is not currently deprecated, but will be eventually.</p>
+</div>
+<div class="section" id="http-request-methods">
+<h3>HTTP Request Methods<a class="headerlink" href="#http-request-methods" title="Permalink to this headline">¶</a></h3>
+<p>The HTTP protocol defines several <a class="reference external" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html">request methods</a> (sometimes referred to as &#8220;verbs&#8221;) for different tasks. GET is the default for all routes with no other method specified. These routes will match GET requests only. To handle other methods such as POST, PUT or DELETE, add a <tt class="docutils literal"><span class="pre">method</span></tt> keyword argument to the <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator or use one of the four alternative decorators: <a class="reference internal" href="api.html#bottle.get" title="bottle.get"><tt class="xref py py-func docutils literal"><span class="pre">get()</span></tt></a>, <a class="reference internal" href="api.html#bottle.post" title="bottle.post"><tt class="xref py py-func docutils literal"><span class="pre">post()</span></tt></a>, <a class="reference internal" href="api.html#bottle.put" title="bottle.put"><tt class="xref py py-func docutils literal"><span class="pre">put()</span></tt></a> or <a class="reference internal" href="api.html#bottle.delete" title="bottle.delete"><tt class="xref py py-func docutils literal"><span class="pre">delete()</span></tt></a>.</p>
+<p>The POST method is commonly used for HTML form submission. This example shows how to handle a login form using POST:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">get</span><span class="p">,</span> <span class="n">post</span><span class="p">,</span> <span class="n">request</span>
+
+<span class="nd">@get</span><span class="p">(</span><span class="s">&#39;/login&#39;</span><span class="p">)</span> <span class="c"># or @route(&#39;/login&#39;)</span>
+<span class="k">def</span> <span class="nf">login_form</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&#39;&#39;&#39;&lt;form method=&quot;POST&quot; action=&quot;/login&quot;&gt;</span>
+<span class="s">                &lt;input name=&quot;name&quot;     type=&quot;text&quot; /&gt;</span>
+<span class="s">                &lt;input name=&quot;password&quot; type=&quot;password&quot; /&gt;</span>
+<span class="s">                &lt;input type=&quot;submit&quot; /&gt;</span>
+<span class="s">              &lt;/form&gt;&#39;&#39;&#39;</span>
+
+<span class="nd">@post</span><span class="p">(</span><span class="s">&#39;/login&#39;</span><span class="p">)</span> <span class="c"># or @route(&#39;/login&#39;, method=&#39;POST&#39;)</span>
+<span class="k">def</span> <span class="nf">login_submit</span><span class="p">():</span>
+    <span class="n">name</span>     <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">)</span>
+    <span class="n">password</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;password&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">check_login</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">&quot;&lt;p&gt;Your login was correct&lt;/p&gt;&quot;</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&quot;&lt;p&gt;Login failed&lt;/p&gt;&quot;</span>
+</pre></div>
+</div>
+<p>In this example the <tt class="docutils literal"><span class="pre">/login</span></tt> URL is linked to two distinct callbacks, one for GET requests and another for POST requests. The first one displays a HTML form to the user. The second callback is invoked on a form submission and checks the login credentials the user entered into the form. The use of <tt class="xref py py-attr docutils literal"><span class="pre">Request.forms</span></tt> is further described in the <a class="reference internal" href="#tutorial-request"><em>Request Data</em></a> section.</p>
+<p class="rubric">Special Methods: HEAD and ANY</p>
+<p>The HEAD method is used to ask for the response identical to the one that would correspond to a GET request, but without the response body. This is useful for retrieving meta-information about a resource without having to download the entire document. Bottle handles these requests automatically by falling back to the corresponding GET route and cutting off the request body, if present. You don&#8217;t have to specify any HEAD routes yourself.</p>
+<p>Additionally, the non-standard ANY method works as a low priority fallback: Routes that listen to ANY will match requests regardless of their HTTP method but only if no other more specific route is defined. This is helpful for <em>proxy-routes</em> that redirect requests to more specific sub-applications.</p>
+<p>To sum it up: HEAD requests fall back to GET routes and all requests fall back to ANY routes, but only if there is no matching route for the original request method. It&#8217;s as simple as that.</p>
+</div>
+<div class="section" id="routing-static-files">
+<h3>Routing Static Files<a class="headerlink" href="#routing-static-files" title="Permalink to this headline">¶</a></h3>
+<p>Static files such as images or CSS files are not served automatically. You have to add a route and a callback to control which files get served and where to find them:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">static_file</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/static/&lt;filename&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">server_static</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/path/to/your/static/files&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>The <tt class="xref py py-func docutils literal"><span class="pre">static_file()</span></tt> function is a helper to serve files in a safe and convenient way (see <a class="reference internal" href="#tutorial-static-files"><em>Static Files</em></a>). This example is limited to files directly within the <tt class="docutils literal"><span class="pre">/path/to/your/static/files</span></tt> directory because the <tt class="docutils literal"><span class="pre">&lt;filename&gt;</span></tt> wildcard won&#8217;t match a path with a slash in it. To serve files in subdirectories, change the wildcard to use the <cite>path</cite> filter:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/static/&lt;filepath:path&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">server_static</span><span class="p">(</span><span class="n">filepath</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">filepath</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/path/to/your/static/files&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Be careful when specifying a relative root-path such as <tt class="docutils literal"><span class="pre">root='./static/files'</span></tt>. The working directory (<tt class="docutils literal"><span class="pre">./</span></tt>) and the project directory are not always the same.</p>
+</div>
+<div class="section" id="error-pages">
+<span id="tutorial-errorhandling"></span><h3>Error Pages<a class="headerlink" href="#error-pages" title="Permalink to this headline">¶</a></h3>
+<p>If anything goes wrong, Bottle displays an informative but fairly plain error page. You can override the default for a specific HTTP status code with the <a class="reference internal" href="api.html#bottle.error" title="bottle.error"><tt class="xref py py-func docutils literal"><span class="pre">error()</span></tt></a> decorator:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">error</span>
+<span class="nd">@error</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">error404</span><span class="p">(</span><span class="n">error</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;Nothing here, sorry&#39;</span>
+</pre></div>
+</div>
+<p>From now on, <cite>404 File not Found</cite> errors will display a custom error page to the user. The only parameter passed to the error-handler is an instance of <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a>. Apart from that, an error-handler is quite similar to a regular request callback. You can read from <a class="reference internal" href="api.html#bottle.request" title="bottle.request"><tt class="xref py py-data docutils literal"><span class="pre">request</span></tt></a>, write to <a class="reference internal" href="api.html#bottle.response" title="bottle.response"><tt class="xref py py-data docutils literal"><span class="pre">response</span></tt></a> and return any supported data-type except for <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> instances.</p>
+<p>Error handlers are used only if your application returns or raises an <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> exception (<tt class="xref py py-func docutils literal"><span class="pre">abort()</span></tt> does just that). Changing <tt class="xref py py-attr docutils literal"><span class="pre">Request.status</span></tt> or returning <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> won&#8217;t trigger the error handler.</p>
+</div>
+</div>
+<div class="section" id="generating-content">
+<span id="tutorial-output"></span><h2>Generating content<a class="headerlink" href="#generating-content" title="Permalink to this headline">¶</a></h2>
+<p>In pure WSGI, the range of types you may return from your application is very limited. Applications must return an iterable yielding byte strings. You may return a string (because strings are iterable) but this causes most servers to transmit your content char by char. Unicode strings are not allowed at all. This is not very practical.</p>
+<p>Bottle is much more flexible and supports a wide range of types. It even adds a <tt class="docutils literal"><span class="pre">Content-Length</span></tt> header if possible and encodes unicode automatically, so you don&#8217;t have to. What follows is a list of data types you may return from your application callbacks and a short description of how these are handled by the framework:</p>
+<dl class="docutils">
+<dt>Dictionaries</dt>
+<dd>As mentioned above, Python dictionaries (or subclasses thereof) are automatically transformed into JSON strings and returned to the browser with the <tt class="docutils literal"><span class="pre">Content-Type</span></tt> header set to <tt class="docutils literal"><span class="pre">application/json</span></tt>. This makes it easy to implement json-based APIs. Data formats other than json are supported too. See the <em class="xref std std-ref">tutorial-output-filter</em> to learn more.</dd>
+<dt>Empty Strings, <tt class="docutils literal"><span class="pre">False</span></tt>, <tt class="docutils literal"><span class="pre">None</span></tt> or other non-true values:</dt>
+<dd>These produce an empty output with the <tt class="docutils literal"><span class="pre">Content-Length</span></tt> header set to 0.</dd>
+<dt>Unicode strings</dt>
+<dd>Unicode strings (or iterables yielding unicode strings) are automatically encoded with the codec specified in the <tt class="docutils literal"><span class="pre">Content-Type</span></tt> header (utf8 by default) and then treated as normal byte strings (see below).</dd>
+<dt>Byte strings</dt>
+<dd>Bottle returns strings as a whole (instead of iterating over each char) and adds a <tt class="docutils literal"><span class="pre">Content-Length</span></tt> header based on the string length. Lists of byte strings are joined first. Other iterables yielding byte strings are not joined because they may grow too big to fit into memory. The <tt class="docutils literal"><span class="pre">Content-Length</span></tt> header is not set in this case.</dd>
+<dt>Instances of <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> or <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a></dt>
+<dd>Returning these has the same effect as when raising them as an exception. In case of an <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a>, the error handler is applied. See <a class="reference internal" href="#tutorial-errorhandling"><em>Error Pages</em></a> for details.</dd>
+<dt>File objects</dt>
+<dd>Everything that has a <tt class="docutils literal"><span class="pre">.read()</span></tt> method is treated as a file or file-like object and passed to the <tt class="docutils literal"><span class="pre">wsgi.file_wrapper</span></tt> callable defined by the WSGI server framework. Some WSGI server implementations can make use of optimized system calls (sendfile) to transmit files more efficiently. In other cases this just iterates over chunks that fit into memory. Optional headers such as <tt class="docutils literal"><span class="pre">Content-Length</span></tt> or <tt class="docutils literal"><span class="pre">Content-Type</span></tt> are <em>not</em> set automatically. Use <tt class="xref py py-func docutils literal"><span class="pre">send_file()</span></tt> if possible. See <a class="reference internal" href="#tutorial-static-files"><em>Static Files</em></a> for details.</dd>
+<dt>Iterables and generators</dt>
+<dd>You are allowed to use <tt class="docutils literal"><span class="pre">yield</span></tt> within your callbacks or return an iterable, as long as the iterable yields byte strings, unicode strings, <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> or <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> instances. Nested iterables are not supported, sorry. Please note that the HTTP status code and the headers are sent to the browser as soon as the iterable yields its first non-empty value. Changing these later has no effect.</dd>
+</dl>
+<p>The ordering of this list is significant. You may for example return a subclass of <tt class="xref py py-class docutils literal"><span class="pre">str</span></tt> with a <tt class="docutils literal"><span class="pre">read()</span></tt> method. It is still treated as a string instead of a file, because strings are handled first.</p>
+<p class="rubric">Changing the Default Encoding</p>
+<p>Bottle uses the <cite>charset</cite> parameter of the <tt class="docutils literal"><span class="pre">Content-Type</span></tt> header to decide how to encode unicode strings. This header defaults to <tt class="docutils literal"><span class="pre">text/html;</span> <span class="pre">charset=UTF8</span></tt> and can be changed using the <tt class="xref py py-attr docutils literal"><span class="pre">Response.content_type</span></tt> attribute or by setting the <tt class="xref py py-attr docutils literal"><span class="pre">Response.charset</span></tt> attribute directly. (The <a class="reference internal" href="api.html#bottle.Response" title="bottle.Response"><tt class="xref py py-class docutils literal"><span class="pre">Response</span></tt></a> object is described in the section <a class="reference internal" href="#tutorial-response"><em>The Response Object</em></a>.)</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">response</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/iso&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">get_iso</span><span class="p">():</span>
+    <span class="n">response</span><span class="o">.</span><span class="n">charset</span> <span class="o">=</span> <span class="s">&#39;ISO-8859-15&#39;</span>
+    <span class="k">return</span> <span class="s">u&#39;This will be sent with ISO-8859-15 encoding.&#39;</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/latin9&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">get_latin</span><span class="p">():</span>
+    <span class="n">response</span><span class="o">.</span><span class="n">content_type</span> <span class="o">=</span> <span class="s">&#39;text/html; charset=latin9&#39;</span>
+    <span class="k">return</span> <span class="s">u&#39;ISO-8859-15 is also known as latin9.&#39;</span>
+</pre></div>
+</div>
+<p>In some rare cases the Python encoding names differ from the names supported by the HTTP specification. Then, you have to do both: first set the <tt class="xref py py-attr docutils literal"><span class="pre">Response.content_type</span></tt> header (which is sent to the client unchanged) and then set the <tt class="xref py py-attr docutils literal"><span class="pre">Response.charset</span></tt> attribute (which is used to encode unicode).</p>
+<div class="section" id="static-files">
+<span id="tutorial-static-files"></span><h3>Static Files<a class="headerlink" href="#static-files" title="Permalink to this headline">¶</a></h3>
+<p>You can directly return file objects, but <tt class="xref py py-func docutils literal"><span class="pre">static_file()</span></tt> is the recommended way to serve static files. It automatically guesses a mime-type, adds a <tt class="docutils literal"><span class="pre">Last-Modified</span></tt> header, restricts paths to a <tt class="docutils literal"><span class="pre">root</span></tt> directory for security reasons and generates appropriate error responses (401 on permission errors, 404 on missing files). It even supports the <tt class="docutils literal"><span class="pre">If-Modified-Since</span></tt> header and eventually generates a <tt class="docutils literal"><span class="pre">304</span> <span class="pre">Not</span> <span class="pre">Modified</span></tt> response. You can pass a custom MIME type to disable guessing.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">static_file</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/images/&lt;filename:re:.*\.png&gt;#&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">send_image</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/path/to/image/files&#39;</span><span class="p">,</span> <span class="n">mimetype</span><span class="o">=</span><span class="s">&#39;image/png&#39;</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/static/&lt;filename:path&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">send_static</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/path/to/static/files&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>You can raise the return value of <tt class="xref py py-func docutils literal"><span class="pre">static_file()</span></tt> as an exception if you really need to.</p>
+<p class="rubric">Forced Download</p>
+<p>Most browsers try to open downloaded files if the MIME type is known and assigned to an application (e.g. PDF files). If this is not what you want, you can force a download dialog and even suggest a filename to the user:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/download/&lt;filename:path&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">download</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/path/to/static/files&#39;</span><span class="p">,</span> <span class="n">download</span><span class="o">=</span><span class="n">filename</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>If the <tt class="docutils literal"><span class="pre">download</span></tt> parameter is just <tt class="docutils literal"><span class="pre">True</span></tt>, the original filename is used.</p>
+</div>
+<div class="section" id="http-errors-and-redirects">
+<span id="tutorial-error"></span><h3>HTTP Errors and Redirects<a class="headerlink" href="#http-errors-and-redirects" title="Permalink to this headline">¶</a></h3>
+<p>The <tt class="xref py py-func docutils literal"><span class="pre">abort()</span></tt> function is a shortcut for generating HTTP error pages.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">abort</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/restricted&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">restricted</span><span class="p">():</span>
+    <span class="n">abort</span><span class="p">(</span><span class="mi">401</span><span class="p">,</span> <span class="s">&quot;Sorry, access denied.&quot;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>To redirect a client to a different URL, you can send a <tt class="docutils literal"><span class="pre">303</span> <span class="pre">See</span> <span class="pre">Other</span></tt> response with the <tt class="docutils literal"><span class="pre">Location</span></tt> header set to the new URL. <tt class="xref py py-func docutils literal"><span class="pre">redirect()</span></tt> does that for you:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">redirect</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/wrong/url&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">wrong</span><span class="p">():</span>
+    <span class="n">redirect</span><span class="p">(</span><span class="s">&quot;/right/url&quot;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>You may provide a different HTTP status code as a second parameter.</p>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">Both functions will interrupt your callback code by raising an <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> exception.</p>
+</div>
+<p class="rubric">Other Exceptions</p>
+<p>All exceptions other than <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> or <a class="reference internal" href="api.html#bottle.HTTPError" title="bottle.HTTPError"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPError</span></tt></a> will result in a <tt class="docutils literal"><span class="pre">500</span> <span class="pre">Internal</span> <span class="pre">Server</span> <span class="pre">Error</span></tt> response, so they won&#8217;t crash your WSGI server. You can turn off this behavior to handle exceptions in your middleware by setting <tt class="docutils literal"><span class="pre">bottle.app().catchall</span></tt> to <tt class="docutils literal"><span class="pre">False</span></tt>.</p>
+</div>
+<div class="section" id="the-response-object">
+<span id="tutorial-response"></span><h3>The <a class="reference internal" href="api.html#bottle.Response" title="bottle.Response"><tt class="xref py py-class docutils literal"><span class="pre">Response</span></tt></a> Object<a class="headerlink" href="#the-response-object" title="Permalink to this headline">¶</a></h3>
+<p>Response metadata such as the HTTP status code, response headers and cookies are stored in an object called <a class="reference internal" href="api.html#bottle.response" title="bottle.response"><tt class="xref py py-data docutils literal"><span class="pre">response</span></tt></a> up to the point where they are transmitted to the browser. You can manipulate these metadata directly or use the predefined helper methods to do so. The full API and feature list is described in the API section (see <a class="reference internal" href="api.html#bottle.Response" title="bottle.Response"><tt class="xref py py-class docutils literal"><span class="pre">Response</span></tt></a>), but the most common use cases and features are covered here, too.</p>
+<p class="rubric">Status Code</p>
+<p>The <a class="reference external" href="http_code">HTTP status code</a> controls the behavior of the browser and defaults to <tt class="docutils literal"><span class="pre">200</span> <span class="pre">OK</span></tt>. In most scenarios you won&#8217;t need to set the <tt class="xref py py-attr docutils literal"><span class="pre">Response.status</span></tt> attribute manually, but use the <tt class="xref py py-func docutils literal"><span class="pre">abort()</span></tt> helper or return an <a class="reference internal" href="api.html#bottle.HTTPResponse" title="bottle.HTTPResponse"><tt class="xref py py-exc docutils literal"><span class="pre">HTTPResponse</span></tt></a> instance with the appropriate status code. Any integer is allowed, but codes other than the ones defined by the <a class="reference external" href="http_code">HTTP specification</a> will only confuse the browser and break standards.</p>
+<p class="rubric">Response Header</p>
+<p>Response headers such as <tt class="docutils literal"><span class="pre">Cache-Control</span></tt> or <tt class="docutils literal"><span class="pre">Location</span></tt> are defined via <tt class="xref py py-meth docutils literal"><span class="pre">Response.set_header()</span></tt>. This method takes two parameters, a header name and a value. The name part is case-insensitive:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/wiki/&lt;page&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">wiki</span><span class="p">(</span><span class="n">page</span><span class="p">):</span>
+    <span class="n">response</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="s">&#39;Content-Language&#39;</span><span class="p">,</span> <span class="s">&#39;en&#39;</span><span class="p">)</span>
+    <span class="o">...</span>
+</pre></div>
+</div>
+<p>Most headers are unique, meaning that only one header per name is send to the client. Some special headers however are allowed to appear more than once in a response. To add an additional header, use <tt class="xref py py-meth docutils literal"><span class="pre">Response.add_header()</span></tt> instead of <tt class="xref py py-meth docutils literal"><span class="pre">Response.set_header()</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">response</span><span class="o">.</span><span class="n">set_header</span><span class="p">(</span><span class="s">&#39;Set-Cookie&#39;</span><span class="p">,</span> <span class="s">&#39;name=value&#39;</span><span class="p">)</span>
+<span class="n">response</span><span class="o">.</span><span class="n">add_header</span><span class="p">(</span><span class="s">&#39;Set-Cookie&#39;</span><span class="p">,</span> <span class="s">&#39;name2=value2&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Please note that this is just an example. If you want to work with cookies, read <a class="reference internal" href="#tutorial-cookies"><em>ahead</em></a>.</p>
+</div>
+<div class="section" id="cookies">
+<span id="tutorial-cookies"></span><h3>Cookies<a class="headerlink" href="#cookies" title="Permalink to this headline">¶</a></h3>
+<p>A cookie is a named piece of text stored in the user&#8217;s browser profile. You can access previously defined cookies via <tt class="xref py py-meth docutils literal"><span class="pre">Request.get_cookie()</span></tt> and set new cookies with <tt class="xref py py-meth docutils literal"><span class="pre">Response.set_cookie()</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello_again</span><span class="p">():</span>
+    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">get_cookie</span><span class="p">(</span><span class="s">&quot;visited&quot;</span><span class="p">):</span>
+        <span class="k">return</span> <span class="s">&quot;Welcome back! Nice to see you again&quot;</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="s">&quot;visited&quot;</span><span class="p">,</span> <span class="s">&quot;yes&quot;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="s">&quot;Hello there! Nice to meet you&quot;</span>
+</pre></div>
+</div>
+<p>The <tt class="xref py py-meth docutils literal"><span class="pre">Response.set_cookie()</span></tt> method accepts a number of additional keyword arguments that control the cookies lifetime and behavior. Some of the most common settings are described here:</p>
+<ul class="simple">
+<li><strong>max_age:</strong>    Maximum age in seconds. (default: <tt class="docutils literal"><span class="pre">None</span></tt>)</li>
+<li><strong>expires:</strong>    A datetime object or UNIX timestamp. (default: <tt class="docutils literal"><span class="pre">None</span></tt>)</li>
+<li><strong>domain:</strong>     The domain that is allowed to read the cookie. (default: current domain)</li>
+<li><strong>path:</strong>       Limit the cookie to a given path (default: <tt class="docutils literal"><span class="pre">/</span></tt>)</li>
+<li><strong>secure:</strong>     Limit the cookie to HTTPS connections (default: off).</li>
+<li><strong>httponly:</strong>   Prevent client-side javascript to read this cookie (default: off, requires Python 2.6 or newer).</li>
+</ul>
+<p>If neither <cite>expires</cite> nor <cite>max_age</cite> is set, the cookie expires at the end of the browser session or as soon as the browser window is closed. There are some other gotchas you should consider when using cookies:</p>
+<ul class="simple">
+<li>Cookies are limited to 4 KB of text in most browsers.</li>
+<li>Some users configure their browsers to not accept cookies at all. Most search engines ignore cookies too. Make sure that your application still works without cookies.</li>
+<li>Cookies are stored at client side and are not encrypted in any way. Whatever you store in a cookie, the user can read it. Worse than that, an attacker might be able to steal a user&#8217;s cookies through <a class="reference external" href="http://en.wikipedia.org/wiki/HTTP_cookie#Cookie_theft_and_session_hijacking">XSS</a> vulnerabilities on your side. Some viruses are known to read the browser cookies, too. Thus, never store confidential information in cookies.</li>
+<li>Cookies are easily forged by malicious clients. Do not trust cookies.</li>
+</ul>
+<p class="rubric" id="tutorial-signed-cookies">Signed Cookies</p>
+<p>As mentioned above, cookies are easily forged by malicious clients. Bottle can cryptographically sign your cookies to prevent this kind of manipulation. All you have to do is to provide a signature key via the <cite>secret</cite> keyword argument whenever you read or set a cookie and keep that key a secret. As a result, <tt class="xref py py-meth docutils literal"><span class="pre">Request.get_cookie()</span></tt> will return <tt class="docutils literal"><span class="pre">None</span></tt> if the cookie is not signed or the signature keys don&#8217;t match:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/login&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">login</span><span class="p">():</span>
+    <span class="n">username</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;username&#39;</span><span class="p">)</span>
+    <span class="n">password</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;password&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">check_user_credentials</span><span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
+        <span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="s">&quot;account&quot;</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">secret</span><span class="o">=</span><span class="s">&#39;some-secret-key&#39;</span><span class="p">)</span>
+        <span class="k">return</span> <span class="s">&quot;Welcome </span><span class="si">%s</span><span class="s">! You are now logged in.&quot;</span> <span class="o">%</span> <span class="n">username</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&quot;Login failed.&quot;</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/restricted&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">restricted_area</span><span class="p">():</span>
+    <span class="n">username</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">get_cookie</span><span class="p">(</span><span class="s">&quot;account&quot;</span><span class="p">,</span> <span class="n">secret</span><span class="o">=</span><span class="s">&#39;some-secret-key&#39;</span><span class="p">)</span>
+    <span class="k">if</span> <span class="n">username</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&quot;Hello </span><span class="si">%s</span><span class="s">. Welcome back.&quot;</span> <span class="o">%</span> <span class="n">username</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&quot;You are not logged in. Access denied.&quot;</span>
+</pre></div>
+</div>
+<p>In addition, Bottle automatically pickles and unpickles any data stored to signed cookies. This allows you to store any pickle-able object (not only strings) to cookies, as long as the pickled data does not exceed the 4 KB limit.</p>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">Signed cookies are not encrypted (the client can still see the content) and not copy-protected (the client can restore an old cookie). The main intention is to make pickling and unpickling safe and prevent manipulation, not to store secret information at client side.</p>
+</div>
+</div>
+</div>
+<div class="section" id="request-data">
+<span id="tutorial-request"></span><h2>Request Data<a class="headerlink" href="#request-data" title="Permalink to this headline">¶</a></h2>
+<p>Bottle provides access to HTTP-related metadata such as cookies, headers and POST form data through a global <tt class="docutils literal"><span class="pre">request</span></tt> object. This object always contains information about the <em>current</em> request, as long as it is accessed from within a callback function. This works even in multi-threaded environments where multiple requests are handled at the same time. For details on how a global object can be thread-safe, see <tt class="xref doc docutils literal"><span class="pre">contextlocal</span></tt>.</p>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p>Bottle stores most of the parsed HTTP metadata in <a class="reference internal" href="api.html#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a> instances. These behave like normal dictionaries, but have some additional features: All values in the dictionary are available as attributes. These virtual attributes always return a unicode string, even if the value is missing. In that case, the string is empty.</p>
+<p class="last"><a class="reference internal" href="api.html#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a> is a subclass of <a class="reference internal" href="api.html#bottle.MultiDict" title="bottle.MultiDict"><tt class="xref py py-class docutils literal"><span class="pre">MultiDict</span></tt></a> and can store more than one value per key. The standard dictionary access methods will only return a single value, but the <a class="reference internal" href="api.html#bottle.MultiDict.getall" title="bottle.MultiDict.getall"><tt class="xref py py-meth docutils literal"><span class="pre">MultiDict.getall()</span></tt></a> method returns a (possibly empty) list of all values for a specific key.</p>
+</div>
+<p>The full API and feature list is described in the API section (see <a class="reference internal" href="api.html#bottle.Request" title="bottle.Request"><tt class="xref py py-class docutils literal"><span class="pre">Request</span></tt></a>), but the most common use cases and features are covered here, too.</p>
+<div class="section" id="id3">
+<h3>Cookies<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h3>
+<p>Cookies are stored in <a class="reference internal" href="api.html#bottle.BaseRequest.cookies" title="bottle.BaseRequest.cookies"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.cookies</span></tt></a> as a <a class="reference internal" href="api.html#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a>. The <a class="reference internal" href="api.html#bottle.BaseRequest.get_cookie" title="bottle.BaseRequest.get_cookie"><tt class="xref py py-meth docutils literal"><span class="pre">BaseRequest.get_cookie()</span></tt></a> method allows access to <a class="reference internal" href="#tutorial-signed-cookies"><em>signed cookies</em></a> as described in a separate section. This example shows a simple cookie-based view counter:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/counter&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">counter</span><span class="p">():</span>
+    <span class="n">count</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span> <span class="n">request</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;counter&#39;</span><span class="p">,</span> <span class="s">&#39;0&#39;</span><span class="p">)</span> <span class="p">)</span>
+    <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
+    <span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="s">&#39;counter&#39;</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">count</span><span class="p">))</span>
+    <span class="k">return</span> <span class="s">&#39;You visited this page </span><span class="si">%d</span><span class="s"> times&#39;</span> <span class="o">%</span> <span class="n">count</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="http-headers">
+<h3>HTTP Headers<a class="headerlink" href="#http-headers" title="Permalink to this headline">¶</a></h3>
+<p>All HTTP headers sent by the client (e.g. <tt class="docutils literal"><span class="pre">Referer</span></tt>, <tt class="docutils literal"><span class="pre">Agent</span></tt> or <tt class="docutils literal"><span class="pre">Accept-Language</span></tt>) are stored in a <a class="reference internal" href="api.html#bottle.WSGIHeaderDict" title="bottle.WSGIHeaderDict"><tt class="xref py py-class docutils literal"><span class="pre">WSGIHeaderDict</span></tt></a> and accessible through <a class="reference internal" href="api.html#bottle.BaseRequest.headers" title="bottle.BaseRequest.headers"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.headers</span></tt></a>. A <a class="reference internal" href="api.html#bottle.WSGIHeaderDict" title="bottle.WSGIHeaderDict"><tt class="xref py py-class docutils literal"><span class="pre">WSGIHeaderDict</span></tt></a> is basically a dictionary with case-insensitive keys:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">request</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/is_ajax&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">is_ajax</span><span class="p">():</span>
+    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;X-Requested-With&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s">&#39;XMLHttpRequest&#39;</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&#39;This is an AJAX request&#39;</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&#39;This is a normal request&#39;</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="query-variables">
+<h3>Query Variables<a class="headerlink" href="#query-variables" title="Permalink to this headline">¶</a></h3>
+<p>The query string (as in <tt class="docutils literal"><span class="pre">/forum?id=1&amp;page=5</span></tt>) is commonly used to transmit a small number of key/value pairs to the server. You can use the <a class="reference internal" href="api.html#bottle.BaseRequest.query" title="bottle.BaseRequest.query"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.query</span></tt></a> (a <a class="reference internal" href="api.html#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a>) to access these values and the <a class="reference internal" href="api.html#bottle.BaseRequest.query_string" title="bottle.BaseRequest.query_string"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.query_string</span></tt></a> attribute to get the whole string.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/forum&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">display_forum</span><span class="p">():</span>
+    <span class="n">forum_id</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">id</span>
+    <span class="n">page</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">page</span> <span class="ow">or</span> <span class="s">&#39;1&#39;</span>
+    <span class="k">return</span> <span class="s">&#39;Forum ID: </span><span class="si">%s</span><span class="s"> (page </span><span class="si">%s</span><span class="s">)&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">forum_id</span><span class="p">,</span> <span class="n">page</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="post-form-data-and-file-uploads">
+<h3>POST Form Data and File Uploads<a class="headerlink" href="#post-form-data-and-file-uploads" title="Permalink to this headline">¶</a></h3>
+<p>The request body of <tt class="docutils literal"><span class="pre">POST</span></tt> and <tt class="docutils literal"><span class="pre">PUT</span></tt> requests may contain form data encoded in various formats. The <a class="reference internal" href="api.html#bottle.BaseRequest.forms" title="bottle.BaseRequest.forms"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.forms</span></tt></a> dictionary contains parsed textual form fields, <a class="reference internal" href="api.html#bottle.BaseRequest.files" title="bottle.BaseRequest.files"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.files</span></tt></a> stores file uploads and <a class="reference internal" href="api.html#bottle.BaseRequest.POST" title="bottle.BaseRequest.POST"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.POST</span></tt></a> combines both dictionaries into one. All three are <a class="reference internal" href="api.html#bottle.FormsDict" title="bottle.FormsDict"><tt class="xref py py-class docutils literal"><span class="pre">FormsDict</span></tt></a> instances and are created on demand. File uploads are saved as special <tt class="xref py py-class docutils literal"><span class="pre">cgi.FieldStorage</span></tt> objects along with some metadata. Finally, you can access the raw body data as a file-like object via <a class="reference internal" href="api.html#bottle.BaseRequest.body" title="bottle.BaseRequest.body"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.body</span></tt></a>.</p>
+<p>Here is an example for a simple file upload form:</p>
+<div class="highlight-html"><div class="highlight"><pre><span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">&quot;/upload&quot;</span> <span class="na">method=</span><span class="s">&quot;post&quot;</span> <span class="na">enctype=</span><span class="s">&quot;multipart/form-data&quot;</span><span class="nt">&gt;</span>
+  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;text&quot;</span> <span class="na">name=</span><span class="s">&quot;name&quot;</span> <span class="nt">/&gt;</span>
+  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">&quot;file&quot;</span> <span class="na">name=</span><span class="s">&quot;data&quot;</span> <span class="nt">/&gt;</span>
+<span class="nt">&lt;/form&gt;</span>
+</pre></div>
+</div>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">request</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/upload&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;POST&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">do_upload</span><span class="p">():</span>
+    <span class="n">name</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">forms</span><span class="o">.</span><span class="n">name</span>
+    <span class="n">data</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">files</span><span class="o">.</span><span class="n">data</span>
+    <span class="k">if</span> <span class="n">name</span> <span class="ow">and</span> <span class="n">data</span> <span class="ow">and</span> <span class="n">data</span><span class="o">.</span><span class="n">file</span><span class="p">:</span>
+        <span class="n">raw</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">file</span><span class="o">.</span><span class="n">read</span><span class="p">()</span> <span class="c"># This is dangerous for big files</span>
+        <span class="n">filename</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">filename</span>
+        <span class="k">return</span> <span class="s">&quot;Hello </span><span class="si">%s</span><span class="s">! You uploaded </span><span class="si">%s</span><span class="s"> (</span><span class="si">%d</span><span class="s"> bytes).&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">filename</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">raw</span><span class="p">))</span>
+    <span class="k">return</span> <span class="s">&quot;You missed a field.&quot;</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="unicode-issues">
+<h3>Unicode issues<a class="headerlink" href="#unicode-issues" title="Permalink to this headline">¶</a></h3>
+<p>In <strong>Python 2</strong> all keys and values are byte-strings. If you need unicode, you can call <tt class="xref py py-meth docutils literal"><span class="pre">FormsDict.getunicode()</span></tt> or fetch values via attribute access. Both methods try to decode the string (default: utf8) and return an empty string if that fails. No need to catch <tt class="xref py py-exc docutils literal"><span class="pre">UnicodeError</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">request</span><span class="o">.</span><span class="n">query</span><span class="p">[</span><span class="s">&#39;city&#39;</span><span class="p">]</span>
+<span class="go">&#39;G\xc3\xb6ttingen&#39;  # A utf8 byte string</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">request</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">city</span>
+<span class="go">u&#39;Göttingen&#39;        # The same string as unicode</span>
+</pre></div>
+</div>
+<p>In <strong>Python 3</strong> all strings are unicode, but HTTP is a byte-based wire protocol. The server has to decode the byte strings somehow before they are passed to the application. To be on the safe side, WSGI suggests ISO-8859-1 (aka latin1), a reversible single-byte codec that can be re-encoded with a different encoding later. Bottle does that for <tt class="xref py py-meth docutils literal"><span class="pre">FormsDict.getunicode()</span></tt> and attribute access, but not for the dict-access methods. These return the unchanged values as provided by the server implementation, which is probably not what you want.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">request</span><span class="o">.</span><span class="n">query</span><span class="p">[</span><span class="s">&#39;city&#39;</span><span class="p">]</span>
+<span class="go">&#39;Göttingen&#39; # An utf8 string provisionally decoded as ISO-8859-1 by the server</span>
+<span class="gp">&gt;&gt;&gt; </span><span class="n">request</span><span class="o">.</span><span class="n">query</span><span class="o">.</span><span class="n">city</span>
+<span class="go">&#39;Göttingen&#39;  # The same string correctly re-encoded as utf8 by bottle</span>
+</pre></div>
+</div>
+<p>If you need the whole dictionary with correctly decoded values (e.g. for WTForms), you can call <a class="reference internal" href="api.html#bottle.FormsDict.decode" title="bottle.FormsDict.decode"><tt class="xref py py-meth docutils literal"><span class="pre">FormsDict.decode()</span></tt></a> to get a re-encoded copy.</p>
+</div>
+<div class="section" id="wsgi-environment">
+<h3>WSGI Environment<a class="headerlink" href="#wsgi-environment" title="Permalink to this headline">¶</a></h3>
+<p>Each <a class="reference internal" href="api.html#bottle.BaseRequest" title="bottle.BaseRequest"><tt class="xref py py-class docutils literal"><span class="pre">BaseRequest</span></tt></a> instance wraps a WSGI environment dictionary. The original is stored in <a class="reference internal" href="api.html#bottle.BaseRequest.environ" title="bottle.BaseRequest.environ"><tt class="xref py py-attr docutils literal"><span class="pre">BaseRequest.environ</span></tt></a>, but the request object itself behaves like a dictionary, too. Most of the interesting data is exposed through special methods or attributes, but if you want to access <a class="reference external" href="WSGIspecification">WSGI environ variables</a> directly, you can do so:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/my_ip&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show_ip</span><span class="p">():</span>
+    <span class="n">ip</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;REMOTE_ADDR&#39;</span><span class="p">)</span>
+    <span class="c"># or ip = request.get(&#39;REMOTE_ADDR&#39;)</span>
+    <span class="c"># or ip = request[&#39;REMOTE_ADDR&#39;]</span>
+    <span class="k">return</span> <span class="s">&quot;Your IP is: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">ip</span>
+</pre></div>
+</div>
+</div>
+</div>
+<div class="section" id="templates">
+<span id="tutorial-templates"></span><h2>Templates<a class="headerlink" href="#templates" title="Permalink to this headline">¶</a></h2>
+<p>Bottle comes with a fast and powerful built-in template engine called <a class="reference internal" href="stpl.html"><em>SimpleTemplate Engine</em></a>. To render a template you can use the <a class="reference internal" href="api.html#bottle.template" title="bottle.template"><tt class="xref py py-func docutils literal"><span class="pre">template()</span></tt></a> function or the <a class="reference internal" href="api.html#bottle.view" title="bottle.view"><tt class="xref py py-func docutils literal"><span class="pre">view()</span></tt></a> decorator. All you have to do is to provide the name of the template and the variables you want to pass to the template as keyword arguments. Here’s a simple example of how to render a template:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">)</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello/&lt;name&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;World&#39;</span><span class="p">):</span>
+    <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;hello_template&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This will load the template file <tt class="docutils literal"><span class="pre">hello_template.tpl</span></tt> and render it with the <tt class="docutils literal"><span class="pre">name</span></tt> variable set. Bottle will look for templates in the <tt class="docutils literal"><span class="pre">./views/</span></tt> folder or any folder specified in the <tt class="docutils literal"><span class="pre">bottle.TEMPLATE_PATH</span></tt> list.</p>
+<p>The <a class="reference internal" href="api.html#bottle.view" title="bottle.view"><tt class="xref py py-func docutils literal"><span class="pre">view()</span></tt></a> decorator allows you to return a dictionary with the template variables instead of calling <a class="reference internal" href="api.html#bottle.template" title="bottle.template"><tt class="xref py py-func docutils literal"><span class="pre">template()</span></tt></a>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello&#39;</span><span class="p">)</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/hello/&lt;name&gt;&#39;</span><span class="p">)</span>
+<span class="nd">@view</span><span class="p">(</span><span class="s">&#39;hello_template&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;World&#39;</span><span class="p">):</span>
+    <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">name</span><span class="p">)</span>
+</pre></div>
+</div>
+<p class="rubric">Syntax</p>
+<p>The template syntax is a very thin layer around the Python language. Its main purpose is to ensure correct indentation of blocks, so you can format your template without worrying about indentation. Follow the link for a full syntax description: <a class="reference internal" href="stpl.html"><em>SimpleTemplate Engine</em></a></p>
+<p>Here is an example template:</p>
+<div class="highlight-html+django"><div class="highlight"><pre>%if name == &#39;World&#39;:
+    <span class="nt">&lt;h1&gt;</span>Hello <span class="cp">{{</span><span class="nv">name</span><span class="cp">}}</span>!<span class="nt">&lt;/h1&gt;</span>
+    <span class="nt">&lt;p&gt;</span>This is a test.<span class="nt">&lt;/p&gt;</span>
+%else:
+    <span class="nt">&lt;h1&gt;</span>Hello <span class="cp">{{</span><span class="nv">name.title</span><span class="o">()</span><span class="cp">}}</span>!<span class="nt">&lt;/h1&gt;</span>
+    <span class="nt">&lt;p&gt;</span>How are you?<span class="nt">&lt;/p&gt;</span>
+%end
+</pre></div>
+</div>
+<p class="rubric">Caching</p>
+<p>Templates are cached in memory after compilation. Modifications made to the template files will have no affect until you clear the template cache. Call <tt class="docutils literal"><span class="pre">bottle.TEMPLATES.clear()</span></tt> to do so. Caching is disabled in debug mode.</p>
+</div>
+<div class="section" id="plugins">
+<span id="id4"></span><h2>Plugins<a class="headerlink" href="#plugins" title="Permalink to this headline">¶</a></h2>
+<p class="versionadded">
+<span class="versionmodified">New in version 0.9.</span></p>
+<p>Bottle&#8217;s core features cover most common use-cases, but as a micro-framework it has its limits. This is where &#8220;Plugins&#8221; come into play. Plugins add missing functionality to the framework, integrate third party libraries, or just automate some repetitive work.</p>
+<p>We have a growing <a class="reference internal" href="plugins/index.html"><em>List of available Plugins</em></a> and most plugins are designed to be portable and re-usable across applications. The chances are high that your problem has already been solved and a ready-to-use plugin exists. If not, the <a class="reference internal" href="plugindev.html"><em>Plugin Development Guide</em></a> may help you.</p>
+<p>The effects and APIs of plugins are manifold and depend on the specific plugin. The <tt class="docutils literal"><span class="pre">SQLitePlugin</span></tt> plugin for example detects callbacks that require a <tt class="docutils literal"><span class="pre">db</span></tt> keyword argument and creates a fresh database connection object every time the callback is called. This makes it very convenient to use a database:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">install</span><span class="p">,</span> <span class="n">template</span>
+<span class="kn">from</span> <span class="nn">bottle_sqlite</span> <span class="kn">import</span> <span class="n">SQLitePlugin</span>
+
+<span class="n">install</span><span class="p">(</span><span class="n">SQLitePlugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">))</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/show/&lt;post_id:int&gt;&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="n">db</span><span class="p">,</span> <span class="n">post_id</span><span class="p">):</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;SELECT title, content FROM posts WHERE id = ?&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">post_id</span><span class="p">,))</span>
+    <span class="n">row</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchone</span><span class="p">()</span>
+    <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;show_post&#39;</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="n">row</span><span class="p">[</span><span class="s">&#39;title&#39;</span><span class="p">],</span> <span class="n">text</span><span class="o">=</span><span class="n">row</span><span class="p">[</span><span class="s">&#39;content&#39;</span><span class="p">])</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/contact&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">contact_page</span><span class="p">():</span>
+    <span class="sd">&#39;&#39;&#39; This callback does not need a db connection. Because the &#39;db&#39;</span>
+<span class="sd">        keyword argument is missing, the sqlite plugin ignores this callback</span>
+<span class="sd">        completely. &#39;&#39;&#39;</span>
+    <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;contact&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Other plugin may populate the thread-safe <tt class="xref py py-data docutils literal"><span class="pre">local</span></tt> object, change details of the <a class="reference internal" href="api.html#bottle.request" title="bottle.request"><tt class="xref py py-data docutils literal"><span class="pre">request</span></tt></a> object, filter the data returned by the callback or bypass the callback completely. An &#8220;auth&#8221; plugin for example could check for a valid session and return a login page instead of calling the original callback. What happens exactly depends on the plugin.</p>
+<div class="section" id="application-wide-installation">
+<h3>Application-wide Installation<a class="headerlink" href="#application-wide-installation" title="Permalink to this headline">¶</a></h3>
+<p>Plugins can be installed application-wide or just to some specific routes that need additional functionality. Most plugins can safely be installed to all routes and are smart enough to not add overhead to callbacks that do not need their functionality.</p>
+<p>Let us take the <tt class="docutils literal"><span class="pre">SQLitePlugin</span></tt> plugin for example. It only affects route callbacks that need a database connection. Other routes are left alone. Because of this, we can install the plugin application-wide with no additional overhead.</p>
+<p>To install a plugin, just call <tt class="xref py py-func docutils literal"><span class="pre">install()</span></tt> with the plugin as first argument:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle_sqlite</span> <span class="kn">import</span> <span class="n">SQLitePlugin</span>
+<span class="n">install</span><span class="p">(</span><span class="n">SQLitePlugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">))</span>
+</pre></div>
+</div>
+<p>The plugin is not applied to the route callbacks yet. This is delayed to make sure no routes are missed. You can install plugins first and add routes later, if you want to. The order of installed plugins is significant, though. If a plugin requires a database connection, you need to install the database plugin first.</p>
+<p class="rubric">Uninstall Plugins</p>
+<p>You can use a name, class or instance to <tt class="xref py py-func docutils literal"><span class="pre">uninstall()</span></tt> a previously installed plugin:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">sqlite_plugin</span> <span class="o">=</span> <span class="n">SQLitePlugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">)</span>
+<span class="n">install</span><span class="p">(</span><span class="n">sqlite_plugin</span><span class="p">)</span>
+
+<span class="n">uninstall</span><span class="p">(</span><span class="n">sqlite_plugin</span><span class="p">)</span> <span class="c"># uninstall a specific plugin</span>
+<span class="n">uninstall</span><span class="p">(</span><span class="n">SQLitePlugin</span><span class="p">)</span>  <span class="c"># uninstall all plugins of that type</span>
+<span class="n">uninstall</span><span class="p">(</span><span class="s">&#39;sqlite&#39;</span><span class="p">)</span>      <span class="c"># uninstall all plugins with that name</span>
+<span class="n">uninstall</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>          <span class="c"># uninstall all plugins at once</span>
+</pre></div>
+</div>
+<p>Plugins can be installed and removed at any time, even at runtime while serving requests. This enables some neat tricks (installing slow debugging or profiling plugins only when needed) but should not be overused. Each time the list of plugins changes, the route cache is flushed and all plugins are re-applied.</p>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">The module-level <tt class="xref py py-func docutils literal"><span class="pre">install()</span></tt> and <tt class="xref py py-func docutils literal"><span class="pre">uninstall()</span></tt> functions affect the <a class="reference internal" href="#default-app"><em>Default Application</em></a>. To manage plugins for a specific application, use the corresponding methods on the <a class="reference internal" href="api.html#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> application object.</p>
+</div>
+</div>
+<div class="section" id="route-specific-installation">
+<h3>Route-specific Installation<a class="headerlink" href="#route-specific-installation" title="Permalink to this headline">¶</a></h3>
+<p>The <tt class="docutils literal"><span class="pre">apply</span></tt> parameter of the <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator comes in handy if you want to install plugins to only a small number of routes:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">sqlite_plugin</span> <span class="o">=</span> <span class="n">SQLitePlugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/create&#39;</span><span class="p">,</span> <span class="nb">apply</span><span class="o">=</span><span class="p">[</span><span class="n">sqlite_plugin</span><span class="p">])</span>
+<span class="k">def</span> <span class="nf">create</span><span class="p">(</span><span class="n">db</span><span class="p">):</span>
+    <span class="n">db</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&#39;INSERT INTO ...&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="blacklisting-plugins">
+<h3>Blacklisting Plugins<a class="headerlink" href="#blacklisting-plugins" title="Permalink to this headline">¶</a></h3>
+<p>You may want to explicitly disable a plugin for a number of routes. The <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator has a <tt class="docutils literal"><span class="pre">skip</span></tt> parameter for this purpose:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">sqlite_plugin</span> <span class="o">=</span> <span class="n">SQLitePlugin</span><span class="p">(</span><span class="n">dbfile</span><span class="o">=</span><span class="s">&#39;/tmp/test.db&#39;</span><span class="p">)</span>
+<span class="n">install</span><span class="p">(</span><span class="n">sqlite_plugin</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/open/&lt;db&gt;&#39;</span><span class="p">,</span> <span class="n">skip</span><span class="o">=</span><span class="p">[</span><span class="n">sqlite_plugin</span><span class="p">])</span>
+<span class="k">def</span> <span class="nf">open_db</span><span class="p">(</span><span class="n">db</span><span class="p">):</span>
+    <span class="c"># The &#39;db&#39; keyword argument is not touched by the plugin this time.</span>
+    <span class="k">if</span> <span class="n">db</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;test&#39;</span><span class="p">,</span> <span class="s">&#39;test2&#39;</span><span class="p">):</span>
+        <span class="c"># The plugin handle can be used for runtime configuration, too.</span>
+        <span class="n">sqlite_plugin</span><span class="o">.</span><span class="n">dbfile</span> <span class="o">=</span> <span class="s">&#39;/tmp/</span><span class="si">%s</span><span class="s">.db&#39;</span> <span class="o">%</span> <span class="n">db</span>
+        <span class="k">return</span> <span class="s">&quot;Database File switched to: /tmp/</span><span class="si">%s</span><span class="s">.db&quot;</span> <span class="o">%</span> <span class="n">db</span>
+    <span class="n">abort</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span> <span class="s">&quot;No such database.&quot;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>The <tt class="docutils literal"><span class="pre">skip</span></tt> parameter accepts a single value or a list of values. You can use a name, class or instance to identify the plugin that is to be skipped. Set <tt class="docutils literal"><span class="pre">skip=True</span></tt> to skip all plugins at once.</p>
+</div>
+<div class="section" id="plugins-and-sub-applications">
+<h3>Plugins and Sub-Applications<a class="headerlink" href="#plugins-and-sub-applications" title="Permalink to this headline">¶</a></h3>
+<p>Most plugins are specific to the application they were installed to. Consequently, they should not affect sub-applications mounted with <a class="reference internal" href="api.html#bottle.Bottle.mount" title="bottle.Bottle.mount"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.mount()</span></tt></a>. Here is an example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">root</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+<span class="n">root</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s">&#39;/blog&#39;</span><span class="p">,</span> <span class="n">apps</span><span class="o">.</span><span class="n">blog</span><span class="p">)</span>
+
+<span class="nd">@root.route</span><span class="p">(</span><span class="s">&#39;/contact&#39;</span><span class="p">,</span> <span class="n">template</span><span class="o">=</span><span class="s">&#39;contact&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">contact</span><span class="p">():</span>
+    <span class="k">return</span> <span class="p">{</span><span class="s">&#39;email&#39;</span><span class="p">:</span> <span class="s">&#39;contact@example.com&#39;</span><span class="p">}</span>
+
+<span class="n">root</span><span class="o">.</span><span class="n">install</span><span class="p">(</span><span class="n">plugins</span><span class="o">.</span><span class="n">WTForms</span><span class="p">())</span>
+</pre></div>
+</div>
+<p>Whenever you mount an application, Bottle creates a proxy-route on the main-application that forwards all requests to the sub-application. Plugins are disabled for this kind of proxy-route by default. As a result, our (fictional) <cite>WTForms</cite> plugin affects the <tt class="docutils literal"><span class="pre">/contact</span></tt> route, but does not affect the routes of the <tt class="docutils literal"><span class="pre">/blog</span></tt> sub-application.</p>
+<p>This behavior is intended as a sane default, but can be overridden. The following example re-activates all plugins for a specific proxy-route:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">root</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s">&#39;/blog&#39;</span><span class="p">,</span> <span class="n">apps</span><span class="o">.</span><span class="n">blog</span><span class="p">,</span> <span class="n">skip</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>But there is a snag: The plugin sees the whole sub-application as a single route, namely the proxy-route mentioned above. In order to affect each individual route of the sub-application, you have to install the plugin to the mounted application explicitly.</p>
+</div>
+</div>
+<div class="section" id="development">
+<h2>Development<a class="headerlink" href="#development" title="Permalink to this headline">¶</a></h2>
+<p>So you have learned the basics and want to write your own application? Here are
+some tips that might help you to be more productive.</p>
+<div class="section" id="default-application">
+<span id="default-app"></span><h3>Default Application<a class="headerlink" href="#default-application" title="Permalink to this headline">¶</a></h3>
+<p>Bottle maintains a global stack of <a class="reference internal" href="api.html#bottle.Bottle" title="bottle.Bottle"><tt class="xref py py-class docutils literal"><span class="pre">Bottle</span></tt></a> instances and uses the top of the stack as a default for some of the module-level functions and decorators. The <a class="reference internal" href="api.html#bottle.route" title="bottle.route"><tt class="xref py py-func docutils literal"><span class="pre">route()</span></tt></a> decorator, for example, is a shortcut for calling <a class="reference internal" href="api.html#bottle.Bottle.route" title="bottle.Bottle.route"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.route()</span></tt></a> on the default application:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&#39;Hello World&#39;</span>
+</pre></div>
+</div>
+<p>This is very convenient for small applications and saves you some typing, but also means that, as soon as your module is imported, routes are installed to the global application. To avoid this kind of import side-effects, Bottle offers a second, more explicit way to build applications:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">app</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
+
+<span class="nd">@app.route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&#39;Hello World&#39;</span>
+</pre></div>
+</div>
+<p>Separating the application object improves re-usability a lot, too. Other developers can safely import the <tt class="docutils literal"><span class="pre">app</span></tt> object from your module and use <a class="reference internal" href="api.html#bottle.Bottle.mount" title="bottle.Bottle.mount"><tt class="xref py py-meth docutils literal"><span class="pre">Bottle.mount()</span></tt></a> to merge applications together.</p>
+<p>As an alternative, you can make use of the application stack to isolate your routes while still using the convenient shortcuts:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">default_app</span><span class="o">.</span><span class="n">push</span><span class="p">()</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
+    <span class="k">return</span> <span class="s">&#39;Hello World&#39;</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">default_app</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>Both <a class="reference internal" href="api.html#bottle.app" title="bottle.app"><tt class="xref py py-func docutils literal"><span class="pre">app()</span></tt></a> and <a class="reference internal" href="api.html#bottle.default_app" title="bottle.default_app"><tt class="xref py py-func docutils literal"><span class="pre">default_app()</span></tt></a> are instance of <a class="reference internal" href="api.html#bottle.AppStack" title="bottle.AppStack"><tt class="xref py py-class docutils literal"><span class="pre">AppStack</span></tt></a> and implement a stack-like API. You can push and pop applications from and to the stack as needed. This also helps if you want to import a third party module that does not offer a separate application object:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">default_app</span><span class="o">.</span><span class="n">push</span><span class="p">()</span>
+
+<span class="kn">import</span> <span class="nn">some.module</span>
+
+<span class="n">app</span> <span class="o">=</span> <span class="n">default_app</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="debug-mode">
+<span id="tutorial-debugging"></span><h3>Debug Mode<a class="headerlink" href="#debug-mode" title="Permalink to this headline">¶</a></h3>
+<p>During early development, the debug mode can be very helpful.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">bottle</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>In this mode, Bottle is much more verbose and provides helpful debugging information whenever an error occurs. It also disables some optimisations that might get in your way and adds some checks that warn you about possible misconfiguration.</p>
+<p>Here is an incomplete list of things that change in debug mode:</p>
+<ul class="simple">
+<li>The default error page shows a traceback.</li>
+<li>Templates are not cached.</li>
+<li>Plugins are applied immediately.</li>
+</ul>
+<p>Just make sure not to use the debug mode on a production server.</p>
+</div>
+<div class="section" id="auto-reloading">
+<h3>Auto Reloading<a class="headerlink" href="#auto-reloading" title="Permalink to this headline">¶</a></h3>
+<p>During development, you have to restart the server a lot to test your
+recent changes. The auto reloader can do this for you. Every time you
+edit a module file, the reloader restarts the server process and loads
+the newest version of your code.</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">run</span>
+<span class="n">run</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>How it works: the main process will not start a server, but spawn a new
+child process using the same command line arguments used to start the
+main process. All module-level code is executed at least twice! Be
+careful.</p>
+<p>The child process will have <tt class="docutils literal"><span class="pre">os.environ['BOTTLE_CHILD']</span></tt> set to <tt class="docutils literal"><span class="pre">True</span></tt>
+and start as a normal non-reloading app server. As soon as any of the
+loaded modules changes, the child process is terminated and re-spawned by
+the main process. Changes in template files will not trigger a reload.
+Please use debug mode to deactivate template caching.</p>
+<p>The reloading depends on the ability to stop the child process. If you are
+running on Windows or any other operating system not supporting
+<tt class="docutils literal"><span class="pre">signal.SIGINT</span></tt> (which raises <tt class="docutils literal"><span class="pre">KeyboardInterrupt</span></tt> in Python),
+<tt class="docutils literal"><span class="pre">signal.SIGTERM</span></tt> is used to kill the child. Note that exit handlers and
+finally clauses, etc., are not executed after a <tt class="docutils literal"><span class="pre">SIGTERM</span></tt>.</p>
+</div>
+<div class="section" id="command-line-interface">
+<h3>Command Line Interface<a class="headerlink" href="#command-line-interface" title="Permalink to this headline">¶</a></h3>
+<p>Starting with version 0.10 you can use bottle as a command-line tool:</p>
+<div class="highlight-console"><div class="highlight"><pre><span class="gp">$</span> python -m bottle
+
+<span class="go">Usage: bottle.py [options] package.module:app</span>
+
+<span class="go">Options:</span>
+<span class="go">  -h, --help            show this help message and exit</span>
+<span class="go">  --version             show version number.</span>
+<span class="go">  -b ADDRESS, --bind=ADDRESS</span>
+<span class="go">                        bind socket to ADDRESS.</span>
+<span class="go">  -s SERVER, --server=SERVER</span>
+<span class="go">                        use SERVER as backend.</span>
+<span class="go">  -p PLUGIN, --plugin=PLUGIN</span>
+<span class="go">                        install additional plugin/s.</span>
+<span class="go">  --debug               start server in debug mode.</span>
+<span class="go">  --reload              auto-reload on file changes.</span>
+</pre></div>
+</div>
+<p>The <cite>ADDRESS</cite> field takes an IP address or an IP:PORT pair and defaults to <tt class="docutils literal"><span class="pre">localhost:8080</span></tt>. The other parameters should be self-explanatory.</p>
+<p>Both plugins and applications are specified via import expressions. These consist of an import path (e.g. <tt class="docutils literal"><span class="pre">package.module</span></tt>) and an expression to be evaluated in the namespace of that module, separated by a colon. See <a class="reference internal" href="api.html#bottle.load" title="bottle.load"><tt class="xref py py-func docutils literal"><span class="pre">load()</span></tt></a> for details. Here are some examples:</p>
+<div class="highlight-console"><div class="highlight"><pre><span class="gp">#</span> Grab the <span class="s1">&#39;app&#39;</span> object from the <span class="s1">&#39;myapp.controller&#39;</span> module and
+<span class="gp">#</span> start a paste server on port 80 on all interfaces.
+<span class="go">python -m bottle -server paste -bind 0.0.0.0:80 myapp.controller:app</span>
+
+<span class="gp">#</span> Start a self-reloading development server and serve the global
+<span class="gp">#</span> default application. The routes are defined in <span class="s1">&#39;test.py&#39;</span>
+<span class="go">python -m bottle --debug --reload test</span>
+
+<span class="gp">#</span> Install a custom debug plugin with some parameters
+<span class="go">python -m bottle --debug --reload --plugin &#39;utils:DebugPlugin(exc=True)&#39;&#39; test</span>
+
+<span class="gp">#</span> Serve an application that is created with <span class="s1">&#39;myapp.controller.make_app()&#39;</span>
+<span class="gp">#</span> on demand.
+<span class="go">python -m bottle &#39;myapp.controller:make_app()&#39;&#39;</span>
+</pre></div>
+</div>
+</div>
+</div>
+<div class="section" id="deployment">
+<h2>Deployment<a class="headerlink" href="#deployment" title="Permalink to this headline">¶</a></h2>
+<p>Bottle runs on the built-in <a class="reference external" href="http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server">wsgiref WSGIServer</a>  by default. This non-threading HTTP server is perfectly fine for development and early production, but may become a performance bottleneck when server load increases.</p>
+<p>The easiest way to increase performance is to install a multi-threaded server library like <a class="reference external" href="http://pythonpaste.org/">paste</a> or <a class="reference external" href="http://www.cherrypy.org/">cherrypy</a> and tell Bottle to use that instead of the single-threaded server:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">bottle</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="s">&#39;paste&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This, and many other deployment options are described in a separate article: <a class="reference internal" href="deployment.html"><em>Deployment</em></a></p>
+</div>
+<div class="section" id="glossary">
+<span id="tutorial-glossary"></span><h2>Glossary<a class="headerlink" href="#glossary" title="Permalink to this headline">¶</a></h2>
+<dl class="glossary docutils">
+<dt id="term-callback">callback</dt>
+<dd>Programmer code that is to be called when some external action happens.
+In the context of web frameworks, the mapping between URL paths and
+application code is often achieved by specifying a callback function
+for each URL.</dd>
+<dt id="term-decorator">decorator</dt>
+<dd>A function returning another function, usually applied as a function transformation using the <tt class="docutils literal"><span class="pre">&#64;decorator</span></tt> syntax. See <a class="reference external" href="http://docs.python.org/reference/compound_stmts.html#function">python documentation for function definition</a> for more about decorators.</dd>
+<dt id="term-environ">environ</dt>
+<dd>A structure where information about all documents under the root is
+saved, and used for cross-referencing.  The environment is pickled
+after the parsing stage, so that successive runs only need to read
+and parse new and changed documents.</dd>
+<dt id="term-handler-function">handler function</dt>
+<dd>A function to handle some specific event or situation. In a web
+framework, the application is developed by attaching a handler function
+as callback for each specific URL comprising the application.</dd>
+<dt id="term-source-directory">source directory</dt>
+<dd>The directory which, including its subdirectories, contains all
+source files for one Sphinx project.</dd>
+</dl>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Tutorial</a><ul>
+<li><a class="reference internal" href="#installation">Installation</a></li>
+<li><a class="reference internal" href="#quickstart-hello-world">Quickstart: &#8220;Hello World&#8221;</a><ul>
+<li><a class="reference internal" href="#the-default-application">The <cite>Default Application</cite></a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#request-routing">Request Routing</a><ul>
+<li><a class="reference internal" href="#dynamic-routes">Dynamic Routes</a></li>
+<li><a class="reference internal" href="#http-request-methods">HTTP Request Methods</a></li>
+<li><a class="reference internal" href="#routing-static-files">Routing Static Files</a></li>
+<li><a class="reference internal" href="#error-pages">Error Pages</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#generating-content">Generating content</a><ul>
+<li><a class="reference internal" href="#static-files">Static Files</a></li>
+<li><a class="reference internal" href="#http-errors-and-redirects">HTTP Errors and Redirects</a></li>
+<li><a class="reference internal" href="#the-response-object">The <tt class="docutils literal"><span class="pre">Response</span></tt> Object</a></li>
+<li><a class="reference internal" href="#cookies">Cookies</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#request-data">Request Data</a><ul>
+<li><a class="reference internal" href="#id3">Cookies</a></li>
+<li><a class="reference internal" href="#http-headers">HTTP Headers</a></li>
+<li><a class="reference internal" href="#query-variables">Query Variables</a></li>
+<li><a class="reference internal" href="#post-form-data-and-file-uploads">POST Form Data and File Uploads</a></li>
+<li><a class="reference internal" href="#unicode-issues">Unicode issues</a></li>
+<li><a class="reference internal" href="#wsgi-environment">WSGI Environment</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#templates">Templates</a></li>
+<li><a class="reference internal" href="#plugins">Plugins</a><ul>
+<li><a class="reference internal" href="#application-wide-installation">Application-wide Installation</a></li>
+<li><a class="reference internal" href="#route-specific-installation">Route-specific Installation</a></li>
+<li><a class="reference internal" href="#blacklisting-plugins">Blacklisting Plugins</a></li>
+<li><a class="reference internal" href="#plugins-and-sub-applications">Plugins and Sub-Applications</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#development">Development</a><ul>
+<li><a class="reference internal" href="#default-application">Default Application</a></li>
+<li><a class="reference internal" href="#debug-mode">Debug Mode</a></li>
+<li><a class="reference internal" href="#auto-reloading">Auto Reloading</a></li>
+<li><a class="reference internal" href="#command-line-interface">Command Line Interface</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#deployment">Deployment</a></li>
+<li><a class="reference internal" href="#glossary">Glossary</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="index.html"
+                        title="previous chapter">Bottle: Python Web Framework</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="routing.html"
+                        title="next chapter">Request Routing</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/tutorial.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="routing.html" title="Request Routing"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="index.html" title="Bottle: Python Web Framework"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_tutorial';
+      var disqus_title = 'Tutorial';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file
diff --git a/html/tutorial_app.html b/html/tutorial_app.html
new file mode 100644 (file)
index 0000000..7521e10
--- /dev/null
@@ -0,0 +1,772 @@
+
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Tutorial: Todo-List Application &mdash; Bottle 0.12-dev documentation</title>
+    
+    <link rel="stylesheet" href="_static/bottle.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    '',
+        VERSION:     '0.12-dev',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="shortcut icon" href="_static/favicon.ico"/>
+    <link rel="top" title="Bottle 0.12-dev documentation" href="index.html" />
+    <link rel="next" title="Primer to Asynchronous Applications" href="async.html" />
+    <link rel="prev" title="Bottle-Werkzeug" href="plugins/werkzeug.html" />
+    <link rel="shortcut icon" type="image/x-icon" href="_static/favicon.ico" />
+    <link rel="image_src" type="image/png" href="_static/logo_reddit.png" />
+    <script type="application/javascript" src="_static/default.js"></script>
+    
+     
+
+  </head>
+  <body>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="async.html" title="Primer to Asynchronous Applications"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="plugins/werkzeug.html" title="Bottle-Werkzeug"
+             accesskey="P">previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body">
+            
+  
+  <p style='font-size: 0.75em; color: darkred'><b>Warning:</b> This is a preview for <b>Bottle-0.12-dev</b>, which is
+    not released yet. Switch to the latest <a href="/docs/stable/"><b>stable release</b></a>?</p>
+  
+  
+  <div class="section" id="tutorial-todo-list-application">
+<h1><a class="toc-backref" href="#id1">Tutorial: Todo-List Application</a><a class="headerlink" href="#tutorial-todo-list-application" title="Permalink to this headline">¶</a></h1>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">This tutorial is a work in progess and written by <a class="reference external" href="http://github.com/noisefloor">noisefloor</a>.</p>
+</div>
+<p>This tutorial should give a brief introduction to the <a class="reference external" href="http://bottle.paws.org">Bottle</a> WSGI Framework. The main goal is to be able, after reading through this tutorial, to create a project using Bottle. Within this document, not all abilities will be shown, but at least the main and important ones like routing, utilizing the Bottle template abilities to format output and handling GET / POST parameters.</p>
+<p>To understand the content here, it is not necessary to have a basic knowledge of WSGI, as Bottle tries to keep WSGI away from the user anyway. You should have a fair understanding of the <a class="reference external" href="http://www.python.org">Python</a> programming language. Furthermore, the example used in the tutorial retrieves and stores data in a SQL databse, so a basic idea about SQL helps, but is not a must to understand the concepts of Bottle. Right here, <a class="reference external" href="http://www.sqlite.org">SQLite</a> is used. The output of Bottle sent to the browser is formatted in some examples by the help of HTML. Thus, a basic idea about the common HTML tags does help as well.</p>
+<p>For the sake of introducing Bottle, the Python code &#8220;in between&#8221; is kept short, in order to keep the focus. Also all code within the tutorial is working fine, but you may not necessarily use it &#8220;in the wild&#8221;, e.g. on a public web server. In order to do so, you may add e.g. more error handling, protect the database with a password, test and escape the input etc.</p>
+<div class="contents topic" id="table-of-contents">
+<p class="topic-title first">Table of Contents</p>
+<ul class="simple">
+<li><a class="reference internal" href="#tutorial-todo-list-application" id="id1">Tutorial: Todo-List Application</a><ul>
+<li><a class="reference internal" href="#goals" id="id2">Goals</a></li>
+<li><a class="reference internal" href="#before-we-start" id="id3">Before We Start...</a></li>
+<li><a class="reference internal" href="#using-bottle-for-a-web-based-todo-list" id="id4">Using Bottle for a Web-Based ToDo List</a></li>
+<li><a class="reference internal" href="#server-setup" id="id5">Server Setup</a></li>
+<li><a class="reference internal" href="#final-words" id="id6">Final Words</a></li>
+<li><a class="reference internal" href="#complete-example-listing" id="id7">Complete Example Listing</a></li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="section" id="goals">
+<h2><a class="toc-backref" href="#id2">Goals</a><a class="headerlink" href="#goals" title="Permalink to this headline">¶</a></h2>
+<p>At the end of this tutorial, we will have a simple, web-based ToDo list. The list contains a text (with max 100 characters) and a status (0 for closed, 1 for open) for each item. Through the web-based user interface, open items can be view and edited and new items can be added.</p>
+<p>During development, all pages will be available on <tt class="docutils literal"><span class="pre">localhost</span></tt> only, but later on it will be shown how to adapt the application for a &#8220;real&#8221; server, including how to use with Apache&#8217;s mod_wsgi.</p>
+<p>Bottle will do the routing and format the output, with the help of templates. The items of the list will be stored inside a SQLite database. Reading and  writing the database will be done by Python code.</p>
+<p>We will end up with an application with the following pages and functionality:</p>
+<blockquote>
+<div><ul class="simple">
+<li>start page <tt class="docutils literal"><span class="pre">http://localhost:8080/todo</span></tt></li>
+<li>adding new items to the list: <tt class="docutils literal"><span class="pre">http://localhost:8080/new</span></tt></li>
+<li>page for editing items: <tt class="docutils literal"><span class="pre">http://localhost:8080/edit/:no</span></tt></li>
+<li>validating data assigned by dynamic routes with the &#64;validate decorator</li>
+<li>catching errors</li>
+</ul>
+</div></blockquote>
+</div>
+<div class="section" id="before-we-start">
+<h2><a class="toc-backref" href="#id3">Before We Start...</a><a class="headerlink" href="#before-we-start" title="Permalink to this headline">¶</a></h2>
+<p class="rubric">Install Bottle</p>
+<p>Assuming that you have a fairly new installation of Python (version 2.5 or higher), you only need to install Bottle in addition to that. Bottle has no other dependencies than Python itself.</p>
+<p>You can either manually install Bottle or use Python&#8217;s easy_install: <tt class="docutils literal"><span class="pre">easy_install</span> <span class="pre">bottle</span></tt></p>
+<p class="rubric">Further Software Necessities</p>
+<p>As we use SQLite3 as a database, make sure it is installed. On Linux systems, most distributions have SQLite3 installed by default. SQLite is available for Windows and MacOS X as well and the <cite>sqlite3</cite> module is part of the python standard library.</p>
+<p class="rubric">Create An SQL Database</p>
+<p>First, we need to create the database we use later on. To do so, save the following script in your project directory and run it with python. You can use the interactive interpreter too:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sqlite3</span>
+<span class="n">con</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span> <span class="c"># Warning: This file is created in the current directory</span>
+<span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;CREATE TABLE todo (id INTEGER PRIMARY KEY, task char(100) NOT NULL, status bool NOT NULL)&quot;</span><span class="p">)</span>
+<span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (&#39;Read A-byte-of-python to get a good introduction into Python&#39;,0)&quot;</span><span class="p">)</span>
+<span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (&#39;Visit the Python website&#39;,1)&quot;</span><span class="p">)</span>
+<span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (&#39;Test various editors for and check the syntax highlighting&#39;,1)&quot;</span><span class="p">)</span>
+<span class="n">con</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (&#39;Choose your favorite WSGI-Framework&#39;,0)&quot;</span><span class="p">)</span>
+<span class="n">con</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>This generates a database-file <cite>todo.db</cite> with tables called <tt class="docutils literal"><span class="pre">todo</span></tt> and three columns <tt class="docutils literal"><span class="pre">id</span></tt>, <tt class="docutils literal"><span class="pre">task</span></tt>, and <tt class="docutils literal"><span class="pre">status</span></tt>. <tt class="docutils literal"><span class="pre">id</span></tt> is a unique id for each row, which is used later on to reference the rows. The column <tt class="docutils literal"><span class="pre">task</span></tt> holds the text which describes the task, it can be max 100 characters long. Finally, the column <tt class="docutils literal"><span class="pre">status</span></tt> is used to mark a task as open (value 1) or closed (value 0).</p>
+</div>
+<div class="section" id="using-bottle-for-a-web-based-todo-list">
+<h2><a class="toc-backref" href="#id4">Using Bottle for a Web-Based ToDo List</a><a class="headerlink" href="#using-bottle-for-a-web-based-todo-list" title="Permalink to this headline">¶</a></h2>
+<p>Now it is time to introduce Bottle in order to create a web-based application. But first, we need to look into a basic concept of Bottle: routes.</p>
+<p class="rubric">Understanding routes</p>
+<p>Basically, each page visible in the browser is dynamically generated when the page address is called. Thus, there is no static content. That is exactly what is called a &#8220;route&#8221; within Bottle: a certain address on the server. So, for example, when the page <tt class="docutils literal"><span class="pre">http://localhost:8080/todo</span></tt> is called from the browser, Bottle &#8220;grabs&#8221; the call and checks if there is any (Python) function defined for the route &#8220;todo&#8221;. If so, Bottle will execute the corresponding Python code and return its result.</p>
+<p class="rubric">First Step - Showing All Open Items</p>
+<p>So, after understanding the concept of routes, let&#8217;s create the first one. The goal is to see all open items from the ToDo list:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sqlite3</span>
+<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/todo&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">todo_list</span><span class="p">():</span>
+    <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT id, task FROM todo WHERE status LIKE &#39;1&#39;&quot;</span><span class="p">)</span>
+    <span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+    <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
+
+<span class="n">run</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>Save the code a <tt class="docutils literal"><span class="pre">todo.py</span></tt>, preferably in the same directory as the file <tt class="docutils literal"><span class="pre">todo.db</span></tt>. Otherwise, you need to add the path to <tt class="docutils literal"><span class="pre">todo.db</span></tt> in the <tt class="docutils literal"><span class="pre">sqlite3.connect()</span></tt> statement.</p>
+<p>Let&#8217;s have a look what we just did: We imported the necessary module <tt class="docutils literal"><span class="pre">sqlite3</span></tt> to access to SQLite database and from Bottle we imported <tt class="docutils literal"><span class="pre">route</span></tt> and <tt class="docutils literal"><span class="pre">run</span></tt>. The <tt class="docutils literal"><span class="pre">run()</span></tt> statement simply starts the web server included in Bottle. By default, the web server serves the pages on localhost and port 8080. Furthermore, we imported <tt class="docutils literal"><span class="pre">route</span></tt>, which is the function responsible for Bottle&#8217;s routing. As you can see, we defined one function, <tt class="docutils literal"><span class="pre">todo_list()</span></tt>, with a few lines of code reading from the database. The important point is the <a class="reference external" href="http://docs.python.org/glossary.html#term-decorator">decorator statement</a> <tt class="docutils literal"><span class="pre">&#64;route('/todo')</span></tt> right before the <tt class="docutils literal"><span class="pre">def</span> <span class="pre">todo_list()</span></tt> statement. By doing this, we bind this function to the route <tt class="docutils literal"><span class="pre">/todo</span></tt>, so every time the browsers calls <tt class="docutils literal"><span class="pre">http://localhost:8080/todo</span></tt>, Bottle returns the result of the function <tt class="docutils literal"><span class="pre">todo_list()</span></tt>. That is how routing within bottle works.</p>
+<p>Actually you can bind more than one route to a function. So the following code:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/todo&#39;</span><span class="p">)</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/my_todo_list&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">todo_list</span><span class="p">():</span>
+    <span class="o">...</span>
+</pre></div>
+</div>
+<p>will work fine, too. What will not work is to bind one route to more than one function.</p>
+<p>What you will see in the browser is what is returned, thus the value given by the <tt class="docutils literal"><span class="pre">return</span></tt> statement. In this example, we need to convert <tt class="docutils literal"><span class="pre">result</span></tt> in to a string by <tt class="docutils literal"><span class="pre">str()</span></tt>, as Bottle expects a string or a list of strings from the return statement. But here, the result of the database query is a list of tuples, which is the standard defined by the <a class="reference external" href="http://www.python.org/dev/peps/pep-0249/">Python DB API</a>.</p>
+<p>Now, after understanding the little script above, it is time to execute it and watch the result yourself. Remember that on Linux- / Unix-based systems the file <tt class="docutils literal"><span class="pre">todo.py</span></tt> needs to be executable first. Then, just run <tt class="docutils literal"><span class="pre">python</span> <span class="pre">todo.py</span></tt> and call the page <tt class="docutils literal"><span class="pre">http://localhost:8080/todo</span></tt> in your browser. In case you made no mistake writing the script, the output should look like this:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="p">[(</span><span class="mi">2</span><span class="p">,</span> <span class="s">u&#39;Visit the Python website&#39;</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s">u&#39;Test various editors for and check the syntax highlighting&#39;</span><span class="p">)]</span>
+</pre></div>
+</div>
+<p>If so - congratulations! You are now a successful user of Bottle. In case it did not work and you need to make some changes to the script, remember to stop Bottle serving the page, otherwise the revised version will not be loaded.</p>
+<p>Actually, the output is not really exciting nor nice to read. It is the raw result returned from the SQL query.</p>
+<p>So, in the next step we format the output in a nicer way. But before we do that, we make our life easier.</p>
+<p class="rubric">Debugging and Auto-Reload</p>
+<p>Maybe you already noticed that Bottle sends a short error message to the browser in case something within the script is wrong, e.g. the connection to the database is not working. For debugging purposes it is quite helpful to get more details. This can be easily achieved by adding the following statement to the script:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">run</span><span class="p">,</span> <span class="n">route</span><span class="p">,</span> <span class="n">debug</span>
+<span class="o">...</span>
+<span class="c">#add this at the very end:</span>
+<span class="n">debug</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
+<span class="n">run</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>By enabling &#8220;debug&#8221;, you will get a full stacktrace of the Python interpreter, which usually contains useful information for finding bugs. Furthermore, templates (see below) are not cached, thus changes to templates will take effect without stopping the server.</p>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">That <tt class="docutils literal"><span class="pre">debug(True)</span></tt> is supposed to be used for development only, it should <em>not</em> be used in production environments.</p>
+</div>
+<p>A further quiet nice feature is auto-reloading, which is enabled by modifying the <tt class="docutils literal"><span class="pre">run()</span></tt> statement to</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">run</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This will automatically detect changes to the script and reload the new version once it is called again, without the need to stop and start the server.</p>
+<p>Again, the feature is mainly supposed to be used while development, not on productive systems.</p>
+<p class="rubric">Bottle Template To Format The Output</p>
+<p>Now let&#8217;s have a look at casting the output of the script into a proper format.</p>
+<p>Actually Bottle expects to receive a string or a list of strings from a function and returns them by the help of the built-in server to the browser. Bottle does not bother about the content of the string itself, so it can be text formatted with HTML markup, too.</p>
+<p>Bottle brings its own easy-to-use template engine with it. Templates are stored as separate files having a <tt class="docutils literal"><span class="pre">.tpl</span></tt> extension. The template can be called then from within a function. Templates can contain any type of text (which will be most likely HTML-markup mixed with Python statements). Furthermore, templates can take arguments, e.g. the result set of a database query, which will be then formatted nicely within the template.</p>
+<p>Right here, we are going to cast the result of our query showing the open ToDo items into a simple table with two columns: the first column will contain the ID of the item, the second column the text. The result set is, as seen above, a list of tuples, each tuple contains one set of results.</p>
+<p>To include the template in our example, just add the following lines:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">debug</span><span class="p">,</span> <span class="n">template</span>
+<span class="o">...</span>
+<span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+<span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+<span class="n">output</span> <span class="o">=</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;make_table&#39;</span><span class="p">,</span> <span class="n">rows</span><span class="o">=</span><span class="n">result</span><span class="p">)</span>
+<span class="k">return</span> <span class="n">output</span>
+<span class="o">...</span>
+</pre></div>
+</div>
+<p>So we do here two things: first, we import <tt class="docutils literal"><span class="pre">template</span></tt> from Bottle in order to be able to use templates. Second, we assign the output of the template <tt class="docutils literal"><span class="pre">make_table</span></tt> to the variable <tt class="docutils literal"><span class="pre">output</span></tt>, which is then returned. In addition to calling the template, we assign <tt class="docutils literal"><span class="pre">result</span></tt>, which we received from the database query, to the variable <tt class="docutils literal"><span class="pre">rows</span></tt>, which is later on used within the template. If necessary, you can assign more than one variable / value to a template.</p>
+<p>Templates always return a list of strings, thus there is no need to convert anything. Of course, we can save one line of code by writing <tt class="docutils literal"><span class="pre">return</span> <span class="pre">template('make_table',</span> <span class="pre">rows=result)</span></tt>, which gives exactly the same result as above.</p>
+<p>Now it is time to write the corresponding template, which looks like this:</p>
+<div class="highlight-python"><pre>%#template to generate a HTML table from a list of tuples (or list of lists, or tuple of tuples or ...)
+&lt;p&gt;The open items are as follows:&lt;/p&gt;
+&lt;table border="1"&gt;
+%for row in rows:
+  &lt;tr&gt;
+  %for col in row:
+    &lt;td&gt;{{col}}&lt;/td&gt;
+  %end
+  &lt;/tr&gt;
+%end
+&lt;/table&gt;</pre>
+</div>
+<p>Save the code as <tt class="docutils literal"><span class="pre">make_table.tpl</span></tt> in the same directory where <tt class="docutils literal"><span class="pre">todo.py</span></tt> is stored.</p>
+<p>Let&#8217;s have a look at the code: every line starting with % is interpreted as Python code. Please note that, of course, only valid Python statements are allowed, otherwise the template will raise an exception, just as any other Python code. The other lines are plain HTML markup.</p>
+<p>As you can see, we use Python&#8217;s <tt class="docutils literal"><span class="pre">for</span></tt> statement two times, in order to go through <tt class="docutils literal"><span class="pre">rows</span></tt>. As seen above, <tt class="docutils literal"><span class="pre">rows</span></tt> is a variable which holds the result of the database query, so it is a list of tuples. The first <tt class="docutils literal"><span class="pre">for</span></tt> statement accesses the tuples within the list, the second one the items within the tuple, which are put each into a cell of the table. It is important that you close all <tt class="docutils literal"><span class="pre">for</span></tt>, <tt class="docutils literal"><span class="pre">if</span></tt>, <tt class="docutils literal"><span class="pre">while</span></tt> etc. statements with <tt class="docutils literal"><span class="pre">%end</span></tt>, otherwise the output may not be what you expect.</p>
+<p>If you need to access a variable within a non-Python code line inside the template, you need to put it into double curly braces. This tells the template to insert the actual value of the variable right in place.</p>
+<p>Run the script again and look at the output. Still not really nice, but at least more readable than the list of tuples. Of course, you can spice-up the very simple HTML markup above, e.g. by using in-line styles to get a better looking output.</p>
+<p class="rubric">Using GET and POST Values</p>
+<p>As we can review all open items properly, we move to the next step, which is adding new items to the ToDo list. The new item should be received from a regular HTML-based form, which sends its data by the GET method.</p>
+<p>To do so, we first add a new route to our script and tell the route that it should get GET data:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">debug</span><span class="p">,</span> <span class="n">template</span><span class="p">,</span> <span class="n">request</span>
+<span class="o">...</span>
+<span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;make_table&#39;</span><span class="p">,</span> <span class="n">rows</span><span class="o">=</span><span class="n">result</span><span class="p">)</span>
+<span class="o">...</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/new&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">new_item</span><span class="p">():</span>
+
+    <span class="n">new</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;task&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+
+    <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+
+    <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (?,?)&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">new</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
+    <span class="n">new_id</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">lastrowid</span>
+
+    <span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+    <span class="k">return</span> <span class="s">&#39;&lt;p&gt;The new task was inserted into the database, the ID is </span><span class="si">%s</span><span class="s">&lt;/p&gt;&#39;</span> <span class="o">%</span> <span class="n">new_id</span>
+</pre></div>
+</div>
+<p>To access GET (or POST) data, we need to import <tt class="docutils literal"><span class="pre">request</span></tt> from Bottle. To assign the actual data to a variable, we use the statement <tt class="docutils literal"><span class="pre">request.GET.get('task','').strip()</span></tt> statement, where <tt class="docutils literal"><span class="pre">task</span></tt> is the name of the GET data we want to access. That&#8217;s all. If your GET data has more than one variable, multiple <tt class="docutils literal"><span class="pre">request.GET.get()</span></tt> statements can be used and assigned to other variables.</p>
+<p>The rest of this piece of code is just processing of the gained data: writing to the database, retrieve the corresponding id from the database and generate the output.</p>
+<p>But where do we get the GET data from? Well, we can use a static HTML page holding the form. Or, what we do right now, is to use a template which is output when the route <tt class="docutils literal"><span class="pre">/new</span></tt> is called without GET data.</p>
+<p>The code needs to be extended to:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="o">...</span>
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/new&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">new_item</span><span class="p">():</span>
+
+    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;save&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
+
+        <span class="n">new</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;task&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (?,?)&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">new</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
+        <span class="n">new_id</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">lastrowid</span>
+
+        <span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+        <span class="k">return</span> <span class="s">&#39;&lt;p&gt;The new task was inserted into the database, the ID is </span><span class="si">%s</span><span class="s">&lt;/p&gt;&#39;</span> <span class="o">%</span> <span class="n">new_id</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;new_task.tpl&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p><tt class="docutils literal"><span class="pre">new_task.tpl</span></tt> looks like this:</p>
+<div class="highlight-python"><pre>&lt;p&gt;Add a new task to the ToDo list:&lt;/p&gt;
+&lt;form action="/new" method="GET"&gt;
+&lt;input type="text" size="100" maxlength="100" name="task"&gt;
+&lt;input type="submit" name="save" value="save"&gt;
+&lt;/form&gt;</pre>
+</div>
+<p>That&#8217;s all. As you can see, the template is plain HTML this time.</p>
+<p>Now we are able to extend our to do list.</p>
+<p>By the way, if you prefer to use POST data: this works exactly the same way, just use <tt class="docutils literal"><span class="pre">request.POST.get()</span></tt> instead.</p>
+<p class="rubric">Editing Existing Items</p>
+<p>The last point to do is to enable editing of existing items.</p>
+<p>By using only the routes we know so far it is possible, but may be quite tricky. But Bottle knows something called &#8220;dynamic routes&#8221;, which makes this task quite easy.</p>
+<p>The basic statement for a dynamic route looks like this:</p>
+<div class="highlight-python"><pre>@route('/myroute/:something')</pre>
+</div>
+<p>The key point here is the colon. This tells Bottle to accept for <tt class="docutils literal"><span class="pre">:something</span></tt> any string up to the next slash. Furthermore, the value of <tt class="docutils literal"><span class="pre">something</span></tt> will be passed to the function assigned to that route, so the data can be processed within the function.</p>
+<p>For our ToDo list, we will create a route <tt class="docutils literal"><span class="pre">&#64;route('/edit/:no)</span></tt>, where <tt class="docutils literal"><span class="pre">no</span></tt> is the id of the item to edit.</p>
+<p>The code looks like this:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/edit/:no&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">edit_item</span><span class="p">(</span><span class="n">no</span><span class="p">):</span>
+
+    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;save&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
+        <span class="n">edit</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;task&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+        <span class="n">status</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;status&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+
+        <span class="k">if</span> <span class="n">status</span> <span class="o">==</span> <span class="s">&#39;open&#39;</span><span class="p">:</span>
+            <span class="n">status</span> <span class="o">=</span> <span class="mi">1</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span>
+
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;UPDATE todo SET task = ?, status = ? WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">edit</span><span class="p">,</span> <span class="n">status</span><span class="p">,</span> <span class="n">no</span><span class="p">))</span>
+        <span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+
+        <span class="k">return</span> <span class="s">&#39;&lt;p&gt;The item number </span><span class="si">%s</span><span class="s"> was successfully updated&lt;/p&gt;&#39;</span> <span class="o">%</span> <span class="n">no</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT task FROM todo WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">no</span><span class="p">)))</span>
+        <span class="n">cur_data</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchone</span><span class="p">()</span>
+
+        <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;edit_task&#39;</span><span class="p">,</span> <span class="n">old</span><span class="o">=</span><span class="n">cur_data</span><span class="p">,</span> <span class="n">no</span><span class="o">=</span><span class="n">no</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>It is basically pretty much the same what we already did above when adding new items, like using <tt class="docutils literal"><span class="pre">GET</span></tt> data etc. The main addition here is using the dynamic route <tt class="docutils literal"><span class="pre">:no</span></tt>, which here passes the number to the corresponding function. As you can see, <tt class="docutils literal"><span class="pre">no</span></tt> is used within the function to access the right row of data within the database.</p>
+<p>The template <tt class="docutils literal"><span class="pre">edit_task.tpl</span></tt> called within the function looks like this:</p>
+<div class="highlight-python"><pre>%#template for editing a task
+%#the template expects to receive a value for "no" as well a "old", the text of the selected ToDo item
+&lt;p&gt;Edit the task with ID = {{no}}&lt;/p&gt;
+&lt;form action="/edit/{{no}}" method="get"&gt;
+&lt;input type="text" name="task" value="{{old[0]}}" size="100" maxlength="100"&gt;
+&lt;select name="status"&gt;
+&lt;option&gt;open&lt;/option&gt;
+&lt;option&gt;closed&lt;/option&gt;
+&lt;/select&gt;
+&lt;br/&gt;
+&lt;input type="submit" name="save" value="save"&gt;
+&lt;/form&gt;</pre>
+</div>
+<p>Again, this template is a mix of Python statements and HTML, as already explained above.</p>
+<p>A last word on dynamic routes: you can even use a regular expression for a dynamic route, as demonstrated later.</p>
+<p class="rubric">Validating Dynamic Routes</p>
+<p>Using dynamic routes is fine, but for many cases it makes sense to validate the dynamic part of the route. For example, we expect an integer number in our route for editing above. But if a float, characters or so are received, the Python interpreter throws an exception, which is not what we want.</p>
+<p>For those cases, Bottle offers the <tt class="docutils literal"><span class="pre">&#64;validate</span></tt> decorator, which validates the &#8220;input&#8221; prior to passing it to the function. In order to apply the validator, extend the code as follows:</p>
+<div class="highlight-python"><pre>from bottle import route, run, debug, template, request, validate
+...
+@route('/edit/:no', method='GET')
+@validate(no=int)
+def edit_item(no):
+...</pre>
+</div>
+<p>At first, we imported <tt class="docutils literal"><span class="pre">validate</span></tt> from the Bottle framework, than we apply the &#64;validate-decorator. Right here, we validate if <tt class="docutils literal"><span class="pre">no</span></tt> is an integer. Basically, the validation works with all types of data like floats, lists etc.</p>
+<p>Save the code and call the page again using a &#8220;403 forbidden&#8221; value for <tt class="docutils literal"><span class="pre">:no</span></tt>, e.g. a float. You will receive not an exception, but a &#8220;403 - Forbidden&#8221; error, saying that an integer was expected.</p>
+<p class="rubric">Dynamic Routes Using Regular Expressions</p>
+<p>Bottle can also handle dynamic routes, where the &#8220;dynamic part&#8221; of the route can be a regular expression.</p>
+<p>So, just to demonstrate that, let&#8217;s assume that all single items in our ToDo list should be accessible by their plain number, by a term like e.g. &#8220;item1&#8221;. For obvious reasons, you do not want to create a route for every item. Furthermore, the simple dynamic routes do not work either, as part of the route, the term &#8220;item&#8221; is static.</p>
+<p>As said above, the solution is a regular expression:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/item:item#[1-9]+#&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show_item</span><span class="p">(</span><span class="n">item</span><span class="p">):</span>
+    <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT task FROM todo WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">item</span><span class="p">))</span>
+    <span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&#39;This item number does not exist!&#39;</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="s">&#39;Task: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
+</pre></div>
+</div>
+<p>Of course, this example is somehow artificially constructed - it would be easier to use a plain dynamic route only combined with a validation. Nevertheless, we want to see how regular expression routes work: the line <tt class="docutils literal"><span class="pre">&#64;route(/item:item_#[1-9]+#)</span></tt> starts like a normal route, but the part surrounded by # is interpreted as a regular expression, which is the dynamic part of the route. So in this case, we want to match any digit between 0 and 9. The following function &#8220;show_item&#8221; just checks whether the given item is present in the database or not. In case it is present, the corresponding text of the task is returned. As you can see, only the regular expression part of the route is passed forward. Furthermore, it is always forwarded as a string, even if it is a plain integer number, like in this case.</p>
+<p class="rubric">Returning Static Files</p>
+<p>Sometimes it may become necessary to associate a route not to a Python function, but just return a static file. So if you have for example a help page for your application, you may want to return this page as plain HTML. This works as follows:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">debug</span><span class="p">,</span> <span class="n">template</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">static_file</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/help&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">help</span><span class="p">():</span>
+    <span class="k">return</span> <span class="n">static_file</span><span class="p">(</span><span class="s">&#39;help.html&#39;</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;/path/to/file&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>At first, we need to import the <tt class="docutils literal"><span class="pre">static_file</span></tt> function from Bottle. As you can see, the <tt class="docutils literal"><span class="pre">return</span> <span class="pre">static_file</span></tt> statement replaces the <tt class="docutils literal"><span class="pre">return</span></tt> statement. It takes at least two arguments: the name of the file to be returned and the path to the file. Even if the file is in the same directory as your application, the path needs to be stated. But in this case, you can use <tt class="docutils literal"><span class="pre">'.'</span></tt> as a path, too. Bottle guesses the MIME-type of the file automatically, but in case you like to state it explicitly, add a third argument to <tt class="docutils literal"><span class="pre">static_file</span></tt>, which would be here <tt class="docutils literal"><span class="pre">mimetype='text/html'</span></tt>. <tt class="docutils literal"><span class="pre">static_file</span></tt> works with any type of route, including the dynamic ones.</p>
+<p class="rubric">Returning JSON Data</p>
+<p>There may be cases where you do not want your application to generate the output directly, but return data to be processed further on, e.g. by JavaScript. For those cases, Bottle offers the possibility to return JSON objects, which is sort of standard for exchanging data between web applications. Furthermore, JSON can be processed by many programming languages, including Python</p>
+<p>So, let&#8217;s assume we want to return the data generated in the regular expression route example as a JSON object. The code looks like this:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/json:json#[1-9]+#&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show_json</span><span class="p">(</span><span class="n">json</span><span class="p">):</span>
+    <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT task FROM todo WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">json</span><span class="p">))</span>
+    <span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
+        <span class="k">return</span> <span class="p">{</span><span class="s">&#39;task&#39;</span><span class="p">:</span><span class="s">&#39;This item number does not exist!&#39;</span><span class="p">}</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="p">{</span><span class="s">&#39;Task&#39;</span><span class="p">:</span> <span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]}</span>
+</pre></div>
+</div>
+<p>As you can, that is fairly simple: just return a regular Python dictionary and Bottle will convert it automatically into a JSON object prior to sending. So if you e.g. call &#8220;<a class="reference external" href="http://localhost/json1">http://localhost/json1</a>&#8221; Bottle should in this case return the JSON object <tt class="docutils literal"><span class="pre">{&quot;Task&quot;:</span> <span class="pre">[&quot;Read</span> <span class="pre">A-byte-of-python</span> <span class="pre">to</span> <span class="pre">get</span> <span class="pre">a</span> <span class="pre">good</span> <span class="pre">introduction</span> <span class="pre">into</span> <span class="pre">Python&quot;]}</span></tt>.</p>
+<p class="rubric">Catching Errors</p>
+<p>The next step may is to catch the error with Bottle itself, to keep away any type of error message from the user of your application. To do that, Bottle has an &#8220;error-route&#8221;, which can be a assigned to a HTML-error.</p>
+<p>In our case, we want to catch a 403 error. The code is as follows:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">error</span>
+
+<span class="nd">@error</span><span class="p">(</span><span class="mi">403</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">mistake</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;The parameter you passed has the wrong format!&#39;</span>
+</pre></div>
+</div>
+<p>So, at first we need to import <tt class="docutils literal"><span class="pre">error</span></tt> from Bottle and define a route by <tt class="docutils literal"><span class="pre">error(403)</span></tt>, which catches all &#8220;403 forbidden&#8221; errors. The function &#8220;mistake&#8221; is assigned to that. Please note that <tt class="docutils literal"><span class="pre">error()</span></tt> always passes the error-code to the function - even if you do not need it. Thus, the function always needs to accept one argument, otherwise it will not work.</p>
+<p>Again, you can assign more than one error-route to a function, or catch various errors with one function each. So this code:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@error</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
+<span class="nd">@error</span><span class="p">(</span><span class="mi">403</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">mistake</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;There is something wrong!&#39;</span>
+</pre></div>
+</div>
+<p>works fine, the following one as well:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="nd">@error</span><span class="p">(</span><span class="mi">403</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">mistake403</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;The parameter you passed has the wrong format!&#39;</span>
+
+<span class="nd">@error</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">mistake404</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;Sorry, this page does not exist!&#39;</span>
+</pre></div>
+</div>
+<p class="rubric">Summary</p>
+<p>After going through all the sections above, you should have a brief understanding how the Bottle WSGI framework works. Furthermore you have all the knowledge necessary to use Bottle for your applications.</p>
+<p>The following chapter give a short introduction how to adapt Bottle for larger projects. Furthermore, we will show how to operate Bottle with web servers which perform better on a higher load / more web traffic than the one we used so far.</p>
+</div>
+<div class="section" id="server-setup">
+<h2><a class="toc-backref" href="#id5">Server Setup</a><a class="headerlink" href="#server-setup" title="Permalink to this headline">¶</a></h2>
+<p>So far, we used the standard server used by Bottle, which is the <a class="reference external" href="http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server">WSGI reference Server</a> shipped along with Python. Although this server is perfectly suitable for development purposes, it is not really suitable for larger applications. But before we have a look at the alternatives, let&#8217;s have a look how to tweak the settings of the standard server first.</p>
+<p class="rubric">Running Bottle on a different port and IP</p>
+<p>As standard, Bottle serves the pages on the IP adress 127.0.0.1, also known as <tt class="docutils literal"><span class="pre">localhost</span></tt>, and on port <tt class="docutils literal"><span class="pre">8080</span></tt>. To modify the setting is pretty simple, as additional parameters can be passed to Bottle&#8217;s <tt class="docutils literal"><span class="pre">run()</span></tt> function to change the port and the address.</p>
+<p>To change the port, just add <tt class="docutils literal"><span class="pre">port=portnumber</span></tt> to the run command. So, for example:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">run</span><span class="p">(</span><span class="n">port</span><span class="o">=</span><span class="mi">80</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>would make Bottle listen to port 80.</p>
+<p>To change the IP address where Bottle is listening:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">&#39;123.45.67.89&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Of course, both parameters can be combined, like:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="n">run</span><span class="p">(</span><span class="n">port</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="s">&#39;123.45.67.89&#39;</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>The <tt class="docutils literal"><span class="pre">port</span></tt> and <tt class="docutils literal"><span class="pre">host</span></tt> parameter can also be applied when Bottle is running with a different server, as shown in the following section.</p>
+<p class="rubric">Running Bottle with a different server</p>
+<p>As said above, the standard server is perfectly suitable for development, personal use or a small group of people only using your application based on Bottle. For larger tasks, the standard server may become a bottleneck, as it is single-threaded, thus it can only serve one request at a time.</p>
+<p>But Bottle has already various adapters to multi-threaded servers on board, which perform better on higher load. Bottle supports <a class="reference external" href="http://www.cherrypy.org/">Cherrypy</a>, <a class="reference external" href="http://github.com/william-os4y/fapws3">Fapws3</a>, <a class="reference external" href="http://trac.saddi.com/flup">Flup</a> and <a class="reference external" href="http://pythonpaste.org/">Paste</a>.</p>
+<p>If you want to run for example Bottle with the Paste server, use the following code:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">PasteServer</span>
+<span class="o">...</span>
+<span class="n">run</span><span class="p">(</span><span class="n">server</span><span class="o">=</span><span class="n">PasteServer</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>This works exactly the same way with <tt class="docutils literal"><span class="pre">FlupServer</span></tt>, <tt class="docutils literal"><span class="pre">CherryPyServer</span></tt> and <tt class="docutils literal"><span class="pre">FapwsServer</span></tt>.</p>
+<p class="rubric">Running Bottle on Apache with mod_wsgi</p>
+<p>Maybe you already have an <a class="reference external" href="http://www.apache.org">Apache</a> or you want to run a Bottle-based application large scale - then it is time to think about Apache with <a class="reference external" href="http://code.google.com/p/modwsgi/">mod_wsgi</a>.</p>
+<p>We assume that your Apache server is up and running and mod_wsgi is working fine as well. On a lot of Linux distributions, mod_wsgi can be easily installed via whatever package management system is in use.</p>
+<p>Bottle brings an adapter for mod_wsgi with it, so serving your application is an easy task.</p>
+<p>In the following example, we assume that you want to make your application &#8220;ToDo list&#8221; accessible through <tt class="docutils literal"><span class="pre">http://www.mypage.com/todo</span></tt> and your code, templates and SQLite database are stored in the path <tt class="docutils literal"><span class="pre">/var/www/todo</span></tt>.</p>
+<p>When you run your application via mod_wsgi, it is imperative to remove the <tt class="docutils literal"><span class="pre">run()</span></tt> statement from your code, otherwise it won&#8217;t work here.</p>
+<p>After that, create a file called <tt class="docutils literal"><span class="pre">adapter.wsgi</span></tt> with the following content:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">bottle</span>
+
+<span class="n">sys</span><span class="o">.</span><span class="n">path</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;/var/www/todo/&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="o">.</span><span class="n">path</span>
+<span class="n">os</span><span class="o">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">))</span>
+
+<span class="kn">import</span> <span class="nn">todo</span> <span class="c"># This loads your application</span>
+
+<span class="n">application</span> <span class="o">=</span> <span class="n">bottle</span><span class="o">.</span><span class="n">default_app</span><span class="p">()</span>
+</pre></div>
+</div>
+<p>and save it in the same path, <tt class="docutils literal"><span class="pre">/var/www/todo</span></tt>. Actually the name of the file can be anything, as long as the extension is <tt class="docutils literal"><span class="pre">.wsgi</span></tt>. The name is only used to reference the file from your virtual host.</p>
+<p>Finally, we need to add a virtual host to the Apache configuration, which looks like this:</p>
+<div class="highlight-python"><pre>&lt;VirtualHost *&gt;
+    ServerName mypage.com
+
+    WSGIDaemonProcess todo user=www-data group=www-data processes=1 threads=5
+    WSGIScriptAlias / /var/www/todo/adapter.wsgi
+
+    &lt;Directory /var/www/todo&gt;
+        WSGIProcessGroup todo
+        WSGIApplicationGroup %{GLOBAL}
+        Order deny,allow
+        Allow from all
+    &lt;/Directory&gt;
+&lt;/VirtualHost&gt;</pre>
+</div>
+<p>After restarting the server, your ToDo list should be accessible at <tt class="docutils literal"><span class="pre">http://www.mypage.com/todo</span></tt></p>
+</div>
+<div class="section" id="final-words">
+<h2><a class="toc-backref" href="#id6">Final Words</a><a class="headerlink" href="#final-words" title="Permalink to this headline">¶</a></h2>
+<p>Now we are at the end of this introduction and tutorial to Bottle. We learned about the basic concepts of Bottle and wrote a first application using the Bottle framework. In addition to that, we saw how to adapt Bottle for large tasks and serve Bottle through an Apache web server with mod_wsgi.</p>
+<p>As said in the introduction, this tutorial is not showing all shades and possibilities of Bottle. What we skipped here is e.g. receiving file objects and streams and how to handle authentication data. Furthermore, we did not show how templates can be called from within another template. For an introduction into those points, please refer to the full <a class="reference external" href="http://bottlepy.org/docs/dev/tutorial.html">Bottle documentation</a> .</p>
+</div>
+<div class="section" id="complete-example-listing">
+<h2><a class="toc-backref" href="#id7">Complete Example Listing</a><a class="headerlink" href="#complete-example-listing" title="Permalink to this headline">¶</a></h2>
+<p>As the ToDo list example was developed piece by piece, here is the complete listing:</p>
+<p>Main code for the application <tt class="docutils literal"><span class="pre">todo.py</span></tt>:</p>
+<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">sqlite3</span>
+<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">route</span><span class="p">,</span> <span class="n">run</span><span class="p">,</span> <span class="n">debug</span><span class="p">,</span> <span class="n">template</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">validate</span><span class="p">,</span> <span class="n">static_file</span><span class="p">,</span> <span class="n">error</span>
+
+<span class="c"># only needed when you run Bottle on mod_wsgi</span>
+<span class="kn">from</span> <span class="nn">bottle</span> <span class="kn">import</span> <span class="n">default_app</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/todo&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">todo_list</span><span class="p">():</span>
+
+    <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT id, task FROM todo WHERE status LIKE &#39;1&#39;;&quot;</span><span class="p">)</span>
+    <span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+    <span class="n">output</span> <span class="o">=</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;make_table&#39;</span><span class="p">,</span> <span class="n">rows</span><span class="o">=</span><span class="n">result</span><span class="p">)</span>
+    <span class="k">return</span> <span class="n">output</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/new&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">new_item</span><span class="p">():</span>
+
+    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;save&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
+
+        <span class="n">new</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;task&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;INSERT INTO todo (task,status) VALUES (?,?)&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">new</span><span class="p">,</span><span class="mi">1</span><span class="p">))</span>
+        <span class="n">new_id</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">lastrowid</span>
+
+        <span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+        <span class="k">return</span> <span class="s">&#39;&lt;p&gt;The new task was inserted into the database, the ID is </span><span class="si">%s</span><span class="s">&lt;/p&gt;&#39;</span> <span class="o">%</span> <span class="n">new_id</span>
+
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;new_task.tpl&#39;</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/edit/:no&#39;</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">&#39;GET&#39;</span><span class="p">)</span>
+<span class="nd">@validate</span><span class="p">(</span><span class="n">no</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">edit_item</span><span class="p">(</span><span class="n">no</span><span class="p">):</span>
+
+    <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;save&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
+        <span class="n">edit</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;task&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+        <span class="n">status</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;status&#39;</span><span class="p">,</span><span class="s">&#39;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
+
+        <span class="k">if</span> <span class="n">status</span> <span class="o">==</span> <span class="s">&#39;open&#39;</span><span class="p">:</span>
+            <span class="n">status</span> <span class="o">=</span> <span class="mi">1</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="n">status</span> <span class="o">=</span> <span class="mi">0</span>
+
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;UPDATE todo SET task = ?, status = ? WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">edit</span><span class="p">,</span><span class="n">status</span><span class="p">,</span><span class="n">no</span><span class="p">))</span>
+        <span class="n">conn</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
+
+        <span class="k">return</span> <span class="s">&#39;&lt;p&gt;The item number </span><span class="si">%s</span><span class="s"> was successfully updated&lt;/p&gt;&#39;</span> <span class="o">%</span><span class="n">no</span>
+
+    <span class="k">else</span><span class="p">:</span>
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT task FROM todo WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">no</span><span class="p">)))</span>
+        <span class="n">cur_data</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchone</span><span class="p">()</span>
+
+        <span class="k">return</span> <span class="n">template</span><span class="p">(</span><span class="s">&#39;edit_task&#39;</span><span class="p">,</span> <span class="n">old</span> <span class="o">=</span> <span class="n">cur_data</span><span class="p">,</span> <span class="n">no</span> <span class="o">=</span> <span class="n">no</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/item:item#[1-9]+#&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show_item</span><span class="p">(</span><span class="n">item</span><span class="p">):</span>
+
+        <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+        <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT task FROM todo WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">item</span><span class="p">))</span>
+        <span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+        <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+        <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
+            <span class="k">return</span> <span class="s">&#39;This item number does not exist!&#39;</span>
+        <span class="k">else</span><span class="p">:</span>
+            <span class="k">return</span> <span class="s">&#39;Task: </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/help&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">help</span><span class="p">():</span>
+
+    <span class="n">static_file</span><span class="p">(</span><span class="s">&#39;help.html&#39;</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="s">&#39;.&#39;</span><span class="p">)</span>
+
+<span class="nd">@route</span><span class="p">(</span><span class="s">&#39;/json:json#[1-9]+#&#39;</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">show_json</span><span class="p">(</span><span class="n">json</span><span class="p">):</span>
+
+    <span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="s">&#39;todo.db&#39;</span><span class="p">)</span>
+    <span class="n">c</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">cursor</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s">&quot;SELECT task FROM todo WHERE id LIKE ?&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">json</span><span class="p">))</span>
+    <span class="n">result</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">fetchall</span><span class="p">()</span>
+    <span class="n">c</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
+
+    <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
+        <span class="k">return</span> <span class="p">{</span><span class="s">&#39;task&#39;</span><span class="p">:</span><span class="s">&#39;This item number does not exist!&#39;</span><span class="p">}</span>
+    <span class="k">else</span><span class="p">:</span>
+        <span class="k">return</span> <span class="p">{</span><span class="s">&#39;Task&#39;</span><span class="p">:</span> <span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">]}</span>
+
+
+<span class="nd">@error</span><span class="p">(</span><span class="mi">403</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">mistake403</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;There is a mistake in your url!&#39;</span>
+
+<span class="nd">@error</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
+<span class="k">def</span> <span class="nf">mistake404</span><span class="p">(</span><span class="n">code</span><span class="p">):</span>
+    <span class="k">return</span> <span class="s">&#39;Sorry, this page does not exist!&#39;</span>
+
+
+<span class="n">debug</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
+<span class="n">run</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
+<span class="c">#remember to remove reloader=True and debug(True) when you move your application from development to a productive environment</span>
+</pre></div>
+</div>
+<p>Template <tt class="docutils literal"><span class="pre">make_table.tpl</span></tt>:</p>
+<div class="highlight-python"><pre>%#template to generate a HTML table from a list of tuples (or list of lists, or tuple of tuples or ...)
+&lt;p&gt;The open items are as follows:&lt;/p&gt;
+&lt;table border="1"&gt;
+%for row in rows:
+  &lt;tr&gt;
+  %for col in row:
+    &lt;td&gt;{{col}}&lt;/td&gt;
+  %end
+  &lt;/tr&gt;
+%end
+&lt;/table&gt;</pre>
+</div>
+<p>Template <tt class="docutils literal"><span class="pre">edit_task.tpl</span></tt>:</p>
+<div class="highlight-python"><pre>%#template for editing a task
+%#the template expects to receive a value for "no" as well a "old", the text of the selected ToDo item
+&lt;p&gt;Edit the task with ID = {{no}}&lt;/p&gt;
+&lt;form action="/edit/{{no}}" method="get"&gt;
+&lt;input type="text" name="task" value="{{old[0]}}" size="100" maxlength="100"&gt;
+&lt;select name="status"&gt;
+&lt;option&gt;open&lt;/option&gt;
+&lt;option&gt;closed&lt;/option&gt;
+&lt;/select&gt;
+&lt;br/&gt;
+&lt;input type="submit" name="save" value="save"&gt;
+&lt;/form&gt;</pre>
+</div>
+<p>Template <tt class="docutils literal"><span class="pre">new_task.tpl</span></tt>:</p>
+<div class="highlight-python"><pre>%#template for the form for a new task
+&lt;p&gt;Add a new task to the ToDo list:&lt;/p&gt;
+&lt;form action="/new" method="GET"&gt;
+&lt;input type="text" size="100" maxlength="100" name="task"&gt;
+&lt;input type="submit" name="save" value="save"&gt;
+&lt;/form&gt;</pre>
+</div>
+</div>
+</div>
+
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar">
+        <div class="sphinxsidebarwrapper">
+            <p class="logo"><a href="index.html">
+              <img class="logo" src="_static/logo_nav.png" alt="Logo"/>
+            </a></p>
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Tutorial: Todo-List Application</a><ul>
+<li><a class="reference internal" href="#goals">Goals</a></li>
+<li><a class="reference internal" href="#before-we-start">Before We Start...</a></li>
+<li><a class="reference internal" href="#using-bottle-for-a-web-based-todo-list">Using Bottle for a Web-Based ToDo List</a></li>
+<li><a class="reference internal" href="#server-setup">Server Setup</a></li>
+<li><a class="reference internal" href="#final-words">Final Words</a></li>
+<li><a class="reference internal" href="#complete-example-listing">Complete Example Listing</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="plugins/werkzeug.html"
+                        title="previous chapter">Bottle-Werkzeug</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="async.html"
+                        title="next chapter">Primer to Asynchronous Applications</a></p>
+  
+
+  <h3>This Page</h3>
+  <ul class="this-page-menu">
+    <li><a href="https://github.com/defnull/bottle/blob/master/docs/tutorial_app.rst" rel="nofollow">Show Source @GitHub</a></li>
+  </ul>
+
+
+<h3>Like it?</h3>
+<ul>
+  <li>
+    <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+
+      <a href="http://flattr.com/thing/21888/Bottle-A-Python-Web-Framework" target="_blank">
+        <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr this" title="Flattr this" border="0" />
+      </a>
+
+      <iframe style="border: 0; margin: 0; padding: 0;"
+        src="https://www.gittip.com/defnull/widget.html" 
+        width="48pt" height="20pt">
+      </iframe>
+
+      <input type="hidden" name="cmd" value="_s-xclick">
+      <input type="hidden" name="hosted_button_id" value="10013866">
+      <input type="image" src="_static/paypal.png" border="0" name="submit" alt="Donate with PayPal!">
+      <img alt="" border="0" src="https://www.paypal.com/de_DE/i/scr/pixel.gif" width="1" height="1">
+    </form>
+
+  </li>
+</ul>
+<div id="searchbox" style="display: none">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <input type="text" name="q" />
+      <input type="submit" value="Go" />
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+    <p class="searchtip" style="font-size: 90%">
+    Enter search terms or a module, class or function name.
+    </p>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="py-modindex.html" title="Python Module Index"
+             >modules</a> |</li>
+        <li class="right" >
+          <a href="async.html" title="Primer to Asynchronous Applications"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="plugins/werkzeug.html" title="Bottle-Werkzeug"
+             >previous</a> |</li>
+    <li><a href="/">Project Home</a> &raquo;</li>
+    
+        <li><a href="index.html">Bottle 0.12-dev documentation</a> &raquo;</li>
+      </ul>
+    </div>
+    <div id="disqus_thread" style="margin: 2em 0;"></div>
+    <script type="text/javascript">
+      var disqus_shortname = 'bottlepy';
+      var disqus_identifier = 'docs_tutorial_app';
+      var disqus_title = 'Tutorial: Todo-List Application';
+      //var disqus_url = 'http://example.com/permalink-to-page.html';
+      (function() {
+        var dsq = document.createElement('script');
+        dsq.type = 'text/javascript';
+        dsq.async = true;
+        dsq.src = 'http://zodbbook.disqus.com/embed.js';
+        document.getElementsByTagName('head')[0].appendChild(dsq);
+      })();
+    </script>
+    <div class="footer">
+    &copy; <a href="index.html#license">Copyright</a> 2009-2012, Marcel Hellkamp - <a href="contact.html">Contact</a><br />
+    Last updated on Nov 11, 2012. Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.<br />
+    Powered by Bottle 0
+    </div>
+
+  </body>
+</html>
\ No newline at end of file