46b413229d3d flask

Bundle Flask.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Fri, 11 Jun 2010 20:12:23 -0400
parents 07c3f5360b22
children b2bd9c232faa
branches/tags flask
files bundled/flask/AUTHORS bundled/flask/CHANGES bundled/flask/LICENSE bundled/flask/MANIFEST.in bundled/flask/Makefile bundled/flask/README bundled/flask/flask.py bundled/flask/setup.cfg bundled/flask/setup.py

Changes

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/AUTHORS	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,24 @@
+Flask is written and maintained by Armin Ronacher and
+various contributors:
+
+Development Lead
+````````````````
+
+- Armin Ronacher <armin.ronacher@active-4.com>
+
+Patches and Suggestions
+```````````````````````
+
+- Chris Edgemon
+- Chris Grindstaff
+- Florent Xicluna
+- Georg Brandl
+- Justin Quick
+- Kenneth Reitz
+- Marian Sigler
+- Matthew Frazier
+- Ron DuPlain
+- Sebastien Estienne
+- Simon Sapin
+- Stephane Wirtel
+- Zhao Xiaohong
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/CHANGES	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,73 @@
+Flask Changelog
+===============
+
+Here you can see the full list of changes between each Flask release.
+
+Version 0.4
+-----------
+
+Release date to be announced, codename to be selected.
+
+- added the ability to register application wide error handlers
+  from modules.
+- :meth:`~flask.Flask.after_request` handlers are now also invoked
+  if the request dies with an exception and an error handling page
+  kicks in.
+- test client has not the ability to preserve the request context
+  for a little longer.  This can also be used to trigger custom
+  requests that do not pop the request stack for testing.
+- because the Python standard library caches loggers, the name of
+  the logger is configurable now to better support unittests.
+- added `TESTING` switch that can activate unittesting helpers.
+
+Version 0.3.1
+-------------
+
+Bugfix release, released May 28th
+
+- fixed a error reporting bug with :meth:`flask.Config.from_envvar`
+- removed some unused code from flask
+- release does no longer include development leftover files (.git
+  folder for themes, built documentation in zip and pdf file and
+  some .pyc files)
+
+Version 0.3
+-----------
+
+Released on May 28th, codename Schnaps
+
+- added support for categories for flashed messages.
+- the application now configures a :class:`logging.Handler` and will
+  log request handling exceptions to that logger when not in debug
+  mode.  This makes it possible to receive mails on server errors
+  for example.
+- added support for context binding that does not require the use of
+  the with statement for playing in the console.
+- the request context is now available within the with statement making
+  it possible to further push the request context or pop it.
+- added support for configurations.
+
+Version 0.2
+-----------
+
+Released on May 12th, codename Jägermeister
+
+- various bugfixes
+- integrated JSON support
+- added :func:`~flask.get_template_attribute` helper function.
+- :meth:`~flask.Flask.add_url_rule` can now also register a
+  view function.
+- refactored internal request dispatching.
+- server listens on 127.0.0.1 by default now to fix issues with chrome.
+- added external URL support.
+- added support for :func:`~flask.send_file`
+- module support and internal request handling refactoring
+  to better support pluggable applications.
+- sessions can be set to be permanent now on a per-session basis.
+- better error reporting on missing secret keys.
+- added support for Google Appengine.
+
+Version 0.1
+-----------
+
+First public preview release.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/LICENSE	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,32 @@
+Copyright (c) 2010 by Armin Ronacher and contributors.  See AUTHORS
+for more details.
+
+Some rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the following
+  disclaimer in the documentation and/or other materials provided
+  with the distribution.
+
+* The names of the contributors may not be used to endorse or
+  promote products derived from this software without specific
+  prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/MANIFEST.in	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,10 @@
+include Makefile CHANGES LICENSE AUTHORS
+recursive-include tests *
+recursive-include examples *
+recursive-include docs *
+recursive-exclude docs *.pyc
+recursive-exclude docs *.pyo
+recursive-exclude examples *.pyc
+recursive-exclude examples *.pyo
+prune docs/_build
+prune docs/_themes/.git
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/Makefile	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,22 @@
+.PHONY: clean-pyc test upload-docs
+
+all: clean-pyc test
+
+test:
+	python setup.py test
+
+release:
+	python setup.py release sdist upload
+
+clean-pyc:
+	find . -name '*.pyc' -exec rm -f {} +
+	find . -name '*.pyo' -exec rm -f {} +
+	find . -name '*~' -exec rm -f {} +
+
+upload-docs:
+	$(MAKE) -C docs html dirhtml latex
+	$(MAKE) -C docs/_build/latex all-pdf
+	cd docs/_build/; mv html flask-docs; zip -r flask-docs.zip flask-docs; mv flask-docs html
+	scp -r docs/_build/dirhtml/* pocoo.org:/var/www/flask.pocoo.org/docs/
+	scp -r docs/_build/latex/Flask.pdf pocoo.org:/var/www/flask.pocoo.org/docs/flask-docs.pdf
+	scp -r docs/_build/flask-docs.zip pocoo.org:/var/www/flask.pocoo.org/docs/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/README	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,36 @@
+
+                          // Flask //
+
+              web development, one drop at a time
+
+
+    ~ What is Flask?
+
+      Flask is a microframework for Python based on Werkzeug
+      and Jinja2.  It's intended for small scale applications
+      and was developped with best intentions in mind.
+
+    ~ Is it ready?
+
+      A preview release is out now, and I'm hoping for some
+      input about what you want from a microframework and
+      how it should look like.  Consider the API to slightly
+      improve over time.
+
+    ~ What do I need?
+
+      Jinja 2.4 and Werkzeug 0.6.1.  `easy_install` will
+      install them for you if you do `easy_install Flask==dev`.
+      I encourage you to use a virtualenv.  Check the docs for
+      complete installation and usage instructions.
+
+    ~ Where are the docs?
+
+      Go to http://flask.pocoo.org/ for a prebuilt version of
+      the current documentation.  Otherwise build them yourself
+      from the sphinx sources in the docs folder.
+
+    ~ Where can I get help?
+
+      Either use the #pocoo IRC channel on irc.freenode.net or
+      ask on the mailinglist: http://flask.pocoo.org/mailinglist/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/flask.py	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,1512 @@
+# -*- coding: utf-8 -*-
+"""
+    flask
+    ~~~~~
+
+    A microframework based on Werkzeug.  It's extensively documented
+    and follows best practice patterns.
+
+    :copyright: (c) 2010 by Armin Ronacher.
+    :license: BSD, see LICENSE for more details.
+"""
+from __future__ import with_statement
+import os
+import sys
+import mimetypes
+from datetime import datetime, timedelta
+
+from itertools import chain
+from threading import Lock
+from jinja2 import Environment, PackageLoader, FileSystemLoader
+from werkzeug import Request as RequestBase, Response as ResponseBase, \
+     LocalStack, LocalProxy, create_environ, SharedDataMiddleware, \
+     ImmutableDict, cached_property, wrap_file, Headers, \
+     import_string
+from werkzeug.routing import Map, Rule
+from werkzeug.exceptions import HTTPException, InternalServerError
+from werkzeug.contrib.securecookie import SecureCookie
+
+# try to load the best simplejson implementation available.  If JSON
+# is not installed, we add a failing class.
+json_available = True
+try:
+    import simplejson as json
+except ImportError:
+    try:
+        import json
+    except ImportError:
+        json_available = False
+
+# utilities we import from Werkzeug and Jinja2 that are unused
+# in the module but are exported as public interface.
+from werkzeug import abort, redirect
+from jinja2 import Markup, escape
+
+# use pkg_resource if that works, otherwise fall back to cwd.  The
+# current working directory is generally not reliable with the notable
+# exception of google appengine.
+try:
+    import pkg_resources
+    pkg_resources.resource_stream
+except (ImportError, AttributeError):
+    pkg_resources = None
+
+# a lock used for logger initialization
+_logger_lock = Lock()
+
+
+class Request(RequestBase):
+    """The request object used by default in flask.  Remembers the
+    matched endpoint and view arguments.
+
+    It is what ends up as :class:`~flask.request`.  If you want to replace
+    the request object used you can subclass this and set
+    :attr:`~flask.Flask.request_class` to your subclass.
+    """
+
+    endpoint = view_args = routing_exception = None
+
+    @property
+    def module(self):
+        """The name of the current module"""
+        if self.endpoint and '.' in self.endpoint:
+            return self.endpoint.rsplit('.', 1)[0]
+
+    @cached_property
+    def json(self):
+        """If the mimetype is `application/json` this will contain the
+        parsed JSON data.
+        """
+        if __debug__:
+            _assert_have_json()
+        if self.mimetype == 'application/json':
+            return json.loads(self.data)
+
+
+class Response(ResponseBase):
+    """The response object that is used by default in flask.  Works like the
+    response object from Werkzeug but is set to have a HTML mimetype by
+    default.  Quite often you don't have to create this object yourself because
+    :meth:`~flask.Flask.make_response` will take care of that for you.
+
+    If you want to replace the response object used you can subclass this and
+    set :attr:`~flask.Flask.response_class` to your subclass.
+    """
+    default_mimetype = 'text/html'
+
+
+class _RequestGlobals(object):
+    pass
+
+
+class Session(SecureCookie):
+    """Expands the session with support for switching between permanent
+    and non-permanent sessions.
+    """
+
+    def _get_permanent(self):
+        return self.get('_permanent', False)
+
+    def _set_permanent(self, value):
+        self['_permanent'] = bool(value)
+
+    permanent = property(_get_permanent, _set_permanent)
+    del _get_permanent, _set_permanent
+
+
+class _NullSession(Session):
+    """Class used to generate nicer error messages if sessions are not
+    available.  Will still allow read-only access to the empty session
+    but fail on setting.
+    """
+
+    def _fail(self, *args, **kwargs):
+        raise RuntimeError('the session is unavailable because no secret '
+                           'key was set.  Set the secret_key on the '
+                           'application to something unique and secret')
+    __setitem__ = __delitem__ = clear = pop = popitem = \
+        update = setdefault = _fail
+    del _fail
+
+
+class _RequestContext(object):
+    """The request context contains all request relevant information.  It is
+    created at the beginning of the request and pushed to the
+    `_request_ctx_stack` and removed at the end of it.  It will create the
+    URL adapter and request object for the WSGI environment provided.
+    """
+
+    def __init__(self, app, environ):
+        self.app = app
+        self.url_adapter = app.url_map.bind_to_environ(environ)
+        self.request = app.request_class(environ)
+        self.session = app.open_session(self.request)
+        if self.session is None:
+            self.session = _NullSession()
+        self.g = _RequestGlobals()
+        self.flashes = None
+
+        try:
+            self.request.endpoint, self.request.view_args = \
+                self.url_adapter.match()
+        except HTTPException, e:
+            self.request.routing_exception = e
+
+    def push(self):
+        """Binds the request context."""
+        _request_ctx_stack.push(self)
+
+    def pop(self):
+        """Pops the request context."""
+        _request_ctx_stack.pop()
+
+    def __enter__(self):
+        self.push()
+        return self
+
+    def __exit__(self, exc_type, exc_value, tb):
+        # do not pop the request stack if we are in debug mode and an
+        # exception happened.  This will allow the debugger to still
+        # access the request object in the interactive shell.  Furthermore
+        # the context can be force kept alive for the test client.
+        if not self.request.environ.get('flask._preserve_context') and \
+           (tb is None or not self.app.debug):
+            self.pop()
+
+
+def url_for(endpoint, **values):
+    """Generates a URL to the given endpoint with the method provided.
+    The endpoint is relative to the active module if modules are in use.
+
+    Here some examples:
+
+    ==================== ======================= =============================
+    Active Module        Target Endpoint         Target Function
+    ==================== ======================= =============================
+    `None`               ``'index'``             `index` of the application
+    `None`               ``'.index'``            `index` of the application
+    ``'admin'``          ``'index'``             `index` of the `admin` module
+    any                  ``'.index'``            `index` of the application
+    any                  ``'admin.index'``       `index` of the `admin` module
+    ==================== ======================= =============================
+
+    Variable arguments that are unknown to the target endpoint are appended
+    to the generated URL as query arguments.
+
+    For more information, head over to the :ref:`Quickstart <url-building>`.
+
+    :param endpoint: the endpoint of the URL (name of the function)
+    :param values: the variable arguments of the URL rule
+    :param _external: if set to `True`, an absolute URL is generated.
+    """
+    ctx = _request_ctx_stack.top
+    if '.' not in endpoint:
+        mod = ctx.request.module
+        if mod is not None:
+            endpoint = mod + '.' + endpoint
+    elif endpoint.startswith('.'):
+        endpoint = endpoint[1:]
+    external = values.pop('_external', False)
+    return ctx.url_adapter.build(endpoint, values, force_external=external)
+
+
+def get_template_attribute(template_name, attribute):
+    """Loads a macro (or variable) a template exports.  This can be used to
+    invoke a macro from within Python code.  If you for example have a
+    template named `_cider.html` with the following contents:
+
+    .. sourcecode:: html+jinja
+
+       {% macro hello(name) %}Hello {{ name }}!{% endmacro %}
+
+    You can access this from Python code like this::
+
+        hello = get_template_attribute('_cider.html', 'hello')
+        return hello('World')
+
+    .. versionadded:: 0.2
+
+    :param template_name: the name of the template
+    :param attribute: the name of the variable of macro to acccess
+    """
+    return getattr(current_app.jinja_env.get_template(template_name).module,
+                   attribute)
+
+
+def flash(message, category='message'):
+    """Flashes a message to the next request.  In order to remove the
+    flashed message from the session and to display it to the user,
+    the template has to call :func:`get_flashed_messages`.
+
+    .. versionchanged: 0.3
+       `category` parameter added.
+
+    :param message: the message to be flashed.
+    :param category: the category for the message.  The following values
+                     are recommended: ``'message'`` for any kind of message,
+                     ``'error'`` for errors, ``'info'`` for information
+                     messages and ``'warning'`` for warnings.  However any
+                     kind of string can be used as category.
+    """
+    session.setdefault('_flashes', []).append((category, message))
+
+
+def get_flashed_messages(with_categories=False):
+    """Pulls all flashed messages from the session and returns them.
+    Further calls in the same request to the function will return
+    the same messages.  By default just the messages are returned,
+    but when `with_categories` is set to `True`, the return value will
+    be a list of tuples in the form ``(category, message)`` instead.
+
+    Example usage:
+
+    .. sourcecode:: html+jinja
+
+        {% for category, msg in get_flashed_messages(with_categories=true) %}
+          <p class=flash-{{ category }}>{{ msg }}
+        {% endfor %}
+
+    .. versionchanged:: 0.3
+       `with_categories` parameter added.
+
+    :param with_categories: set to `True` to also receive categories.
+    """
+    flashes = _request_ctx_stack.top.flashes
+    if flashes is None:
+        _request_ctx_stack.top.flashes = flashes = session.pop('_flashes', [])
+    if not with_categories:
+        return [x[1] for x in flashes]
+    return flashes
+
+
+def jsonify(*args, **kwargs):
+    """Creates a :class:`~flask.Response` with the JSON representation of
+    the given arguments with an `application/json` mimetype.  The arguments
+    to this function are the same as to the :class:`dict` constructor.
+
+    Example usage::
+
+        @app.route('/_get_current_user')
+        def get_current_user():
+            return jsonify(username=g.user.username,
+                           email=g.user.email,
+                           id=g.user.id)
+
+    This will send a JSON response like this to the browser::
+
+        {
+            "username": "admin",
+            "email": "admin@localhost",
+            "id": 42
+        }
+
+    This requires Python 2.6 or an installed version of simplejson.  For
+    security reasons only objects are supported toplevel.  For more
+    information about this, have a look at :ref:`json-security`.
+
+    .. versionadded:: 0.2
+    """
+    if __debug__:
+        _assert_have_json()
+    return current_app.response_class(json.dumps(dict(*args, **kwargs),
+        indent=None if request.is_xhr else 2), mimetype='application/json')
+
+
+def send_file(filename_or_fp, mimetype=None, as_attachment=False,
+              attachment_filename=None):
+    """Sends the contents of a file to the client.  This will use the
+    most efficient method available and configured.  By default it will
+    try to use the WSGI server's file_wrapper support.  Alternatively
+    you can set the application's :attr:`~Flask.use_x_sendfile` attribute
+    to ``True`` to directly emit an `X-Sendfile` header.  This however
+    requires support of the underlying webserver for `X-Sendfile`.
+
+    By default it will try to guess the mimetype for you, but you can
+    also explicitly provide one.  For extra security you probably want
+    to sent certain files as attachment (HTML for instance).
+
+    Please never pass filenames to this function from user sources without
+    checking them first.  Something like this is usually sufficient to
+    avoid security problems::
+
+        if '..' in filename or filename.startswith('/'):
+            abort(404)
+
+    .. versionadded:: 0.2
+
+    :param filename_or_fp: the filename of the file to send.  This is
+                           relative to the :attr:`~Flask.root_path` if a
+                           relative path is specified.
+                           Alternatively a file object might be provided
+                           in which case `X-Sendfile` might not work and
+                           fall back to the traditional method.
+    :param mimetype: the mimetype of the file if provided, otherwise
+                     auto detection happens.
+    :param as_attachment: set to `True` if you want to send this file with
+                          a ``Content-Disposition: attachment`` header.
+    :param attachment_filename: the filename for the attachment if it
+                                differs from the file's filename.
+    """
+    if isinstance(filename_or_fp, basestring):
+        filename = filename_or_fp
+        file = None
+    else:
+        file = filename_or_fp
+        filename = getattr(file, 'name', None)
+    if filename is not None:
+        filename = os.path.join(current_app.root_path, filename)
+    if mimetype is None and (filename or attachment_filename):
+        mimetype = mimetypes.guess_type(filename or attachment_filename)[0]
+    if mimetype is None:
+        mimetype = 'application/octet-stream'
+
+    headers = Headers()
+    if as_attachment:
+        if attachment_filename is None:
+            if filename is None:
+                raise TypeError('filename unavailable, required for '
+                                'sending as attachment')
+            attachment_filename = os.path.basename(filename)
+        headers.add('Content-Disposition', 'attachment',
+                    filename=attachment_filename)
+
+    if current_app.use_x_sendfile and filename:
+        if file is not None:
+            file.close()
+        headers['X-Sendfile'] = filename
+        data = None
+    else:
+        if file is None:
+            file = open(filename, 'rb')
+        data = wrap_file(request.environ, file)
+
+    return Response(data, mimetype=mimetype, headers=headers,
+                    direct_passthrough=True)
+
+
+def render_template(template_name, **context):
+    """Renders a template from the template folder with the given
+    context.
+
+    :param template_name: the name of the template to be rendered
+    :param context: the variables that should be available in the
+                    context of the template.
+    """
+    current_app.update_template_context(context)
+    return current_app.jinja_env.get_template(template_name).render(context)
+
+
+def render_template_string(source, **context):
+    """Renders a template from the given template source string
+    with the given context.
+
+    :param template_name: the sourcecode of the template to be
+                          rendered
+    :param context: the variables that should be available in the
+                    context of the template.
+    """
+    current_app.update_template_context(context)
+    return current_app.jinja_env.from_string(source).render(context)
+
+
+def _default_template_ctx_processor():
+    """Default template context processor.  Injects `request`,
+    `session` and `g`.
+    """
+    reqctx = _request_ctx_stack.top
+    return dict(
+        request=reqctx.request,
+        session=reqctx.session,
+        g=reqctx.g
+    )
+
+
+def _assert_have_json():
+    """Helper function that fails if JSON is unavailable."""
+    if not json_available:
+        raise RuntimeError('simplejson not installed')
+
+
+def _get_package_path(name):
+    """Returns the path to a package or cwd if that cannot be found."""
+    try:
+        return os.path.abspath(os.path.dirname(sys.modules[name].__file__))
+    except (KeyError, AttributeError):
+        return os.getcwd()
+
+
+# figure out if simplejson escapes slashes.  This behaviour was changed
+# from one version to another without reason.
+if not json_available or '\\/' not in json.dumps('/'):
+
+    def _tojson_filter(*args, **kwargs):
+        if __debug__:
+            _assert_have_json()
+        return json.dumps(*args, **kwargs).replace('/', '\\/')
+else:
+    _tojson_filter = json.dumps
+
+
+class _PackageBoundObject(object):
+
+    def __init__(self, import_name):
+        #: The name of the package or module.  Do not change this once
+        #: it was set by the constructor.
+        self.import_name = import_name
+
+        #: Where is the app root located?
+        self.root_path = _get_package_path(self.import_name)
+
+    def open_resource(self, resource):
+        """Opens a resource from the application's resource folder.  To see
+        how this works, consider the following folder structure::
+
+            /myapplication.py
+            /schemal.sql
+            /static
+                /style.css
+            /templates
+                /layout.html
+                /index.html
+
+        If you want to open the `schema.sql` file you would do the
+        following::
+
+            with app.open_resource('schema.sql') as f:
+                contents = f.read()
+                do_something_with(contents)
+
+        :param resource: the name of the resource.  To access resources within
+                         subfolders use forward slashes as separator.
+        """
+        if pkg_resources is None:
+            return open(os.path.join(self.root_path, resource), 'rb')
+        return pkg_resources.resource_stream(self.import_name, resource)
+
+
+class _ModuleSetupState(object):
+
+    def __init__(self, app, url_prefix=None):
+        self.app = app
+        self.url_prefix = url_prefix
+
+
+class Module(_PackageBoundObject):
+    """Container object that enables pluggable applications.  A module can
+    be used to organize larger applications.  They represent blueprints that,
+    in combination with a :class:`Flask` object are used to create a large
+    application.
+
+    A module is like an application bound to an `import_name`.  Multiple
+    modules can share the same import names, but in that case a `name` has
+    to be provided to keep them apart.  If different import names are used,
+    the rightmost part of the import name is used as name.
+
+    Here an example structure for a larger appliation::
+
+        /myapplication
+            /__init__.py
+            /views
+                /__init__.py
+                /admin.py
+                /frontend.py
+
+    The `myapplication/__init__.py` can look like this::
+
+        from flask import Flask
+        from myapplication.views.admin import admin
+        from myapplication.views.frontend import frontend
+
+        app = Flask(__name__)
+        app.register_module(admin, url_prefix='/admin')
+        app.register_module(frontend)
+
+    And here an example view module (`myapplication/views/admin.py`)::
+
+        from flask import Module
+
+        admin = Module(__name__)
+
+        @admin.route('/')
+        def index():
+            pass
+
+        @admin.route('/login')
+        def login():
+            pass
+
+    For a gentle introduction into modules, checkout the
+    :ref:`working-with-modules` section.
+    """
+
+    def __init__(self, import_name, name=None, url_prefix=None):
+        if name is None:
+            assert '.' in import_name, 'name required if package name ' \
+                'does not point to a submodule'
+            name = import_name.rsplit('.', 1)[1]
+        _PackageBoundObject.__init__(self, import_name)
+        self.name = name
+        self.url_prefix = url_prefix
+        self._register_events = []
+
+    def route(self, rule, **options):
+        """Like :meth:`Flask.route` but for a module.  The endpoint for the
+        :func:`url_for` function is prefixed with the name of the module.
+        """
+        def decorator(f):
+            self.add_url_rule(rule, f.__name__, f, **options)
+            return f
+        return decorator
+
+    def add_url_rule(self, rule, endpoint, view_func=None, **options):
+        """Like :meth:`Flask.add_url_rule` but for a module.  The endpoint for
+        the :func:`url_for` function is prefixed with the name of the module.
+        """
+        def register_rule(state):
+            the_rule = rule
+            if state.url_prefix:
+                the_rule = state.url_prefix + rule
+            state.app.add_url_rule(the_rule, '%s.%s' % (self.name, endpoint),
+                                   view_func, **options)
+        self._record(register_rule)
+
+    def before_request(self, f):
+        """Like :meth:`Flask.before_request` but for a module.  This function
+        is only executed before each request that is handled by a function of
+        that module.
+        """
+        self._record(lambda s: s.app.before_request_funcs
+            .setdefault(self.name, []).append(f))
+        return f
+
+    def before_app_request(self, f):
+        """Like :meth:`Flask.before_request`.  Such a function is executed
+        before each request, even if outside of a module.
+        """
+        self._record(lambda s: s.app.before_request_funcs
+            .setdefault(None, []).append(f))
+        return f
+
+    def after_request(self, f):
+        """Like :meth:`Flask.after_request` but for a module.  This function
+        is only executed after each request that is handled by a function of
+        that module.
+        """
+        self._record(lambda s: s.app.after_request_funcs
+            .setdefault(self.name, []).append(f))
+        return f
+
+    def after_app_request(self, f):
+        """Like :meth:`Flask.after_request` but for a module.  Such a function
+        is executed after each request, even if outside of the module.
+        """
+        self._record(lambda s: s.app.after_request_funcs
+            .setdefault(None, []).append(f))
+        return f
+
+    def context_processor(self, f):
+        """Like :meth:`Flask.context_processor` but for a module.  This
+        function is only executed for requests handled by a module.
+        """
+        self._record(lambda s: s.app.template_context_processors
+            .setdefault(self.name, []).append(f))
+        return f
+
+    def app_context_processor(self, f):
+        """Like :meth:`Flask.context_processor` but for a module.  Such a
+        function is executed each request, even if outside of the module.
+        """
+        self._record(lambda s: s.app.template_context_processors
+            .setdefault(None, []).append(f))
+        return f
+
+    def app_errorhandler(self, code):
+        """Like :meth:`Flask.errorhandler` but for a module.  This
+        handler is used for all requests, even if outside of the module.
+
+        .. versionadded:: 0.4
+        """
+        def decorator(f):
+            self._record(lambda s: s.app.errorhandler(code)(f))
+            return f
+        return decorator
+
+    def _record(self, func):
+        self._register_events.append(func)
+
+
+class ConfigAttribute(object):
+    """Makes an attribute forward to the config"""
+
+    def __init__(self, name):
+        self.__name__ = name
+
+    def __get__(self, obj, type=None):
+        if obj is None:
+            return self
+        return obj.config[self.__name__]
+
+    def __set__(self, obj, value):
+        obj.config[self.__name__] = value
+
+
+class Config(dict):
+    """Works exactly like a dict but provides ways to fill it from files
+    or special dictionaries.  There are two common patterns to populate the
+    config.
+
+    Either you can fill the config from a config file::
+
+        app.config.from_pyfile('yourconfig.cfg')
+
+    Or alternatively you can define the configuration options in the
+    module that calls :meth:`from_object` or provide an import path to
+    a module that should be loaded.  It is also possible to tell it to
+    use the same module and with that provide the configuration values
+    just before the call::
+
+        DEBUG = True
+        SECRET_KEY = 'development key'
+        app.config.from_object(__name__)
+
+    In both cases (loading from any Python file or loading from modules),
+    only uppercase keys are added to the config.  This makes it possible to use
+    lowercase values in the config file for temporary values that are not added
+    to the config or to define the config keys in the same file that implements
+    the application.
+
+    Probably the most interesting way to load configurations is from an
+    environment variable pointing to a file::
+
+        app.config.from_envvar('YOURAPPLICATION_SETTINGS')
+
+    In this case before launching the application you have to set this
+    environment variable to the file you want to use.  On Linux and OS X
+    use the export statement::
+
+        export YOURAPPLICATION_SETTINGS='/path/to/config/file'
+
+    On windows use `set` instead.
+
+    :param root_path: path to which files are read relative from.  When the
+                      config object is created by the application, this is
+                      the application's :attr:`~flask.Flask.root_path`.
+    :param defaults: an optional dictionary of default values
+    """
+
+    def __init__(self, root_path, defaults=None):
+        dict.__init__(self, defaults or {})
+        self.root_path = root_path
+
+    def from_envvar(self, variable_name, silent=False):
+        """Loads a configuration from an environment variable pointing to
+        a configuration file.  This basically is just a shortcut with nicer
+        error messages for this line of code::
+
+            app.config.from_pyfile(os.environ['YOURAPPLICATION_SETTINGS'])
+
+        :param variable_name: name of the environment variable
+        :param silent: set to `True` if you want silent failing for missing
+                       files.
+        :return: bool. `True` if able to load config, `False` otherwise.
+        """
+        rv = os.environ.get(variable_name)
+        if not rv:
+            if silent:
+                return False
+            raise RuntimeError('The environment variable %r is not set '
+                               'and as such configuration could not be '
+                               'loaded.  Set this variable and make it '
+                               'point to a configuration file' %
+                               variable_name)
+        self.from_pyfile(rv)
+        return True
+
+    def from_pyfile(self, filename):
+        """Updates the values in the config from a Python file.  This function
+        behaves as if the file was imported as module with the
+        :meth:`from_object` function.
+
+        :param filename: the filename of the config.  This can either be an
+                         absolute filename or a filename relative to the
+                         root path.
+        """
+        filename = os.path.join(self.root_path, filename)
+        d = type(sys)('config')
+        d.__file__ = filename
+        execfile(filename, d.__dict__)
+        self.from_object(d)
+
+    def from_object(self, obj):
+        """Updates the values from the given object.  An object can be of one
+        of the following two types:
+
+        -   a string: in this case the object with that name will be imported
+        -   an actual object reference: that object is used directly
+
+        Objects are usually either modules or classes.
+
+        Just the uppercase variables in that object are stored in the config
+        after lowercasing.  Example usage::
+
+            app.config.from_object('yourapplication.default_config')
+            from yourapplication import default_config
+            app.config.from_object(default_config)
+
+        You should not use this function to load the actual configuration but
+        rather configuration defaults.  The actual config should be loaded
+        with :meth:`from_pyfile` and ideally from a location not within the
+        package because the package might be installed system wide.
+
+        :param obj: an import name or object
+        """
+        if isinstance(obj, basestring):
+            obj = import_string(obj)
+        for key in dir(obj):
+            if key.isupper():
+                self[key] = getattr(obj, key)
+
+    def __repr__(self):
+        return '<%s %s>' % (self.__class__.__name__, dict.__repr__(self))
+
+
+class Flask(_PackageBoundObject):
+    """The flask object implements a WSGI application and acts as the central
+    object.  It is passed the name of the module or package of the
+    application.  Once it is created it will act as a central registry for
+    the view functions, the URL rules, template configuration and much more.
+
+    The name of the package is used to resolve resources from inside the
+    package or the folder the module is contained in depending on if the
+    package parameter resolves to an actual python package (a folder with
+    an `__init__.py` file inside) or a standard module (just a `.py` file).
+
+    For more information about resource loading, see :func:`open_resource`.
+
+    Usually you create a :class:`Flask` instance in your main module or
+    in the `__init__.py` file of your package like this::
+
+        from flask import Flask
+        app = Flask(__name__)
+    """
+
+    #: The class that is used for request objects.  See :class:`~flask.Request`
+    #: for more information.
+    request_class = Request
+
+    #: The class that is used for response objects.  See
+    #: :class:`~flask.Response` for more information.
+    response_class = Response
+
+    #: Path for the static files.  If you don't want to use static files
+    #: you can set this value to `None` in which case no URL rule is added
+    #: and the development server will no longer serve any static files.
+    static_path = '/static'
+
+    #: The debug flag.  Set this to `True` to enable debugging of the
+    #: application.  In debug mode the debugger will kick in when an unhandled
+    #: exception ocurrs and the integrated server will automatically reload
+    #: the application if changes in the code are detected.
+    #:
+    #: This attribute can also be configured from the config with the `DEBUG`
+    #: configuration key.  Defaults to `False`.
+    debug = ConfigAttribute('DEBUG')
+
+    #: The testing flask.  Set this to `True` to enable the test mode of
+    #: Flask extensions (and in the future probably also Flask itself).
+    #: For example this might activate unittest helpers that have an
+    #: additional runtime cost which should not be enabled by default.
+    #:
+    #: This attribute can also be configured from the config with the
+    #: `TESTING` configuration key.  Defaults to `False`.
+    testing = ConfigAttribute('TESTING')
+
+    #: If a secret key is set, cryptographic components can use this to
+    #: sign cookies and other things.  Set this to a complex random value
+    #: when you want to use the secure cookie for instance.
+    #:
+    #: This attribute can also be configured from the config with the
+    #: `SECRET_KEY` configuration key.  Defaults to `None`.
+    secret_key = ConfigAttribute('SECRET_KEY')
+
+    #: The secure cookie uses this for the name of the session cookie.
+    #:
+    #: This attribute can also be configured from the config with the
+    #: `SESSION_COOKIE_NAME` configuration key.  Defaults to ``'session'``
+    session_cookie_name = ConfigAttribute('SESSION_COOKIE_NAME')
+
+    #: A :class:`~datetime.timedelta` which is used to set the expiration
+    #: date of a permanent session.  The default is 31 days which makes a
+    #: permanent session survive for roughly one month.
+    #:
+    #: This attribute can also be configured from the config with the
+    #: `PERMANENT_SESSION_LIFETIME` configuration key.  Defaults to
+    #: ``timedelta(days=31)``
+    permanent_session_lifetime = ConfigAttribute('PERMANENT_SESSION_LIFETIME')
+
+    #: Enable this if you want to use the X-Sendfile feature.  Keep in
+    #: mind that the server has to support this.  This only affects files
+    #: sent with the :func:`send_file` method.
+    #:
+    #: .. versionadded:: 0.2
+    #:
+    #: This attribute can also be configured from the config with the
+    #: `USE_X_SENDFILE` configuration key.  Defaults to `False`.
+    use_x_sendfile = ConfigAttribute('USE_X_SENDFILE')
+
+    #: The name of the logger to use.  By default the logger name is the
+    #: package name passed to the constructor.
+    #:
+    #: .. versionadded:: 0.4
+    logger_name = ConfigAttribute('LOGGER_NAME')
+
+    #: The logging format used for the debug logger.  This is only used when
+    #: the application is in debug mode, otherwise the attached logging
+    #: handler does the formatting.
+    #:
+    #: .. versionadded:: 0.3
+    debug_log_format = (
+        '-' * 80 + '\n' +
+        '%(levelname)s in %(module)s, %(pathname)s:%(lineno)d]:\n' +
+        '%(message)s\n' +
+        '-' * 80
+    )
+
+    #: Options that are passed directly to the Jinja2 environment.
+    jinja_options = ImmutableDict(
+        autoescape=True,
+        extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
+    )
+
+    #: Default configuration parameters.
+    default_config = ImmutableDict({
+        'DEBUG':                                False,
+        'TESTING':                              False,
+        'SECRET_KEY':                           None,
+        'SESSION_COOKIE_NAME':                  'session',
+        'PERMANENT_SESSION_LIFETIME':           timedelta(days=31),
+        'USE_X_SENDFILE':                       False,
+        'LOGGER_NAME':                          None
+    })
+
+    def __init__(self, import_name):
+        _PackageBoundObject.__init__(self, import_name)
+
+        #: The configuration dictionary as :class:`Config`.  This behaves
+        #: exactly like a regular dictionary but supports additional methods
+        #: to load a config from files.
+        self.config = Config(self.root_path, self.default_config)
+
+        #: Prepare the deferred setup of the logger.
+        self._logger = None
+        self.logger_name = self.import_name
+
+        #: A dictionary of all view functions registered.  The keys will
+        #: be function names which are also used to generate URLs and
+        #: the values are the function objects themselves.
+        #: to register a view function, use the :meth:`route` decorator.
+        self.view_functions = {}
+
+        #: A dictionary of all registered error handlers.  The key is
+        #: be the error code as integer, the value the function that
+        #: should handle that error.
+        #: To register a error handler, use the :meth:`errorhandler`
+        #: decorator.
+        self.error_handlers = {}
+
+        #: A dictionary with lists of functions that should be called at the
+        #: beginning of the request.  The key of the dictionary is the name of
+        #: the module this function is active for, `None` for all requests.
+        #: This can for example be used to open database connections or
+        #: getting hold of the currently logged in user.  To register a
+        #: function here, use the :meth:`before_request` decorator.
+        self.before_request_funcs = {}
+
+        #: A dictionary with lists of functions that should be called after
+        #: each request.  The key of the dictionary is the name of the module
+        #: this function is active for, `None` for all requests.  This can for
+        #: example be used to open database connections or getting hold of the
+        #: currently logged in user.  To register a function here, use the
+        #: :meth:`before_request` decorator.
+        self.after_request_funcs = {}
+
+        #: A dictionary with list of functions that are called without argument
+        #: to populate the template context.  They key of the dictionary is the
+        #: name of the module this function is active for, `None` for all
+        #: requests.  Each returns a dictionary that the template context is
+        #: updated with.  To register a function here, use the
+        #: :meth:`context_processor` decorator.
+        self.template_context_processors = {
+            None: [_default_template_ctx_processor]
+        }
+
+        #: The :class:`~werkzeug.routing.Map` for this instance.  You can use
+        #: this to change the routing converters after the class was created
+        #: but before any routes are connected.  Example::
+        #:
+        #:    from werkzeug import BaseConverter
+        #:
+        #:    class ListConverter(BaseConverter):
+        #:        def to_python(self, value):
+        #:            return value.split(',')
+        #:        def to_url(self, values):
+        #:            return ','.join(BaseConverter.to_url(value)
+        #:                            for value in values)
+        #:
+        #:    app = Flask(__name__)
+        #:    app.url_map.converters['list'] = ListConverter
+        self.url_map = Map()
+
+        if self.static_path is not None:
+            self.add_url_rule(self.static_path + '/<filename>',
+                              build_only=True, endpoint='static')
+            if pkg_resources is not None:
+                target = (self.import_name, 'static')
+            else:
+                target = os.path.join(self.root_path, 'static')
+            self.wsgi_app = SharedDataMiddleware(self.wsgi_app, {
+                self.static_path: target
+            })
+
+        #: The Jinja2 environment.  It is created from the
+        #: :attr:`jinja_options` and the loader that is returned
+        #: by the :meth:`create_jinja_loader` function.
+        self.jinja_env = Environment(loader=self.create_jinja_loader(),
+                                     **self.jinja_options)
+        self.jinja_env.globals.update(
+            url_for=url_for,
+            get_flashed_messages=get_flashed_messages
+        )
+        self.jinja_env.filters['tojson'] = _tojson_filter
+
+    @property
+    def logger(self):
+        """A :class:`logging.Logger` object for this application.  The
+        default configuration is to log to stderr if the application is
+        in debug mode.  This logger can be used to (surprise) log messages.
+        Here some examples::
+
+            app.logger.debug('A value for debugging')
+            app.logger.warning('A warning ocurred (%d apples)', 42)
+            app.logger.error('An error occoured')
+
+        .. versionadded:: 0.3
+        """
+        if self._logger and self._logger.name == self.logger_name:
+            return self._logger
+        with _logger_lock:
+            if self._logger and self._logger.name == self.logger_name:
+                return self._logger
+            from logging import getLogger, StreamHandler, Formatter, DEBUG
+            class DebugHandler(StreamHandler):
+                def emit(x, record):
+                    if self.debug:
+                        StreamHandler.emit(x, record)
+            handler = DebugHandler()
+            handler.setLevel(DEBUG)
+            handler.setFormatter(Formatter(self.debug_log_format))
+            logger = getLogger(self.logger_name)
+            logger.addHandler(handler)
+            self._logger = logger
+            return logger
+
+    def create_jinja_loader(self):
+        """Creates the Jinja loader.  By default just a package loader for
+        the configured package is returned that looks up templates in the
+        `templates` folder.  To add other loaders it's possible to
+        override this method.
+        """
+        if pkg_resources is None:
+            return FileSystemLoader(os.path.join(self.root_path, 'templates'))
+        return PackageLoader(self.import_name)
+
+    def update_template_context(self, context):
+        """Update the template context with some commonly used variables.
+        This injects request, session and g into the template context.
+
+        :param context: the context as a dictionary that is updated in place
+                        to add extra variables.
+        """
+        funcs = self.template_context_processors[None]
+        mod = _request_ctx_stack.top.request.module
+        if mod is not None and mod in self.template_context_processors:
+            funcs = chain(funcs, self.template_context_processors[mod])
+        for func in funcs:
+            context.update(func())
+
+    def run(self, host='127.0.0.1', port=5000, **options):
+        """Runs the application on a local development server.  If the
+        :attr:`debug` flag is set the server will automatically reload
+        for code changes and show a debugger in case an exception happened.
+
+        :param host: the hostname to listen on.  set this to ``'0.0.0.0'``
+                     to have the server available externally as well.
+        :param port: the port of the webserver
+        :param options: the options to be forwarded to the underlying
+                        Werkzeug server.  See :func:`werkzeug.run_simple`
+                        for more information.
+        """
+        from werkzeug import run_simple
+        if 'debug' in options:
+            self.debug = options.pop('debug')
+        options.setdefault('use_reloader', self.debug)
+        options.setdefault('use_debugger', self.debug)
+        return run_simple(host, port, self, **options)
+
+    def test_client(self):
+        """Creates a test client for this application.  For information
+        about unit testing head over to :ref:`testing`.
+
+        The test client can be used in a `with` block to defer the closing down
+        of the context until the end of the `with` block.  This is useful if
+        you want to access the context locals for testing::
+
+            with app.test_client() as c:
+                rv = c.get('/?vodka=42')
+                assert request.args['vodka'] == '42'
+
+        .. versionchanged:: 0.4
+           added support for `with` block usage for the client.
+        """
+        from werkzeug import Client
+        class FlaskClient(Client):
+            preserve_context = context_preserved = False
+            def open(self, *args, **kwargs):
+                if self.context_preserved:
+                    _request_ctx_stack.pop()
+                    self.context_preserved = False
+                kwargs.setdefault('environ_overrides', {}) \
+                    ['flask._preserve_context'] = self.preserve_context
+                old = _request_ctx_stack.top
+                try:
+                    return Client.open(self, *args, **kwargs)
+                finally:
+                    self.context_preserved = _request_ctx_stack.top is not old
+            def __enter__(self):
+                self.preserve_context = True
+                return self
+            def __exit__(self, exc_type, exc_value, tb):
+                self.preserve_context = False
+                if self.context_preserved:
+                    _request_ctx_stack.pop()
+        return FlaskClient(self, self.response_class, use_cookies=True)
+
+    def open_session(self, request):
+        """Creates or opens a new session.  Default implementation stores all
+        session data in a signed cookie.  This requires that the
+        :attr:`secret_key` is set.
+
+        :param request: an instance of :attr:`request_class`.
+        """
+        key = self.secret_key
+        if key is not None:
+            return Session.load_cookie(request, self.session_cookie_name,
+                                       secret_key=key)
+
+    def save_session(self, session, response):
+        """Saves the session if it needs updates.  For the default
+        implementation, check :meth:`open_session`.
+
+        :param session: the session to be saved (a
+                        :class:`~werkzeug.contrib.securecookie.SecureCookie`
+                        object)
+        :param response: an instance of :attr:`response_class`
+        """
+        expires = None
+        if session.permanent:
+            expires = datetime.utcnow() + self.permanent_session_lifetime
+        session.save_cookie(response, self.session_cookie_name,
+                            expires=expires, httponly=True)
+
+    def register_module(self, module, **options):
+        """Registers a module with this application.  The keyword argument
+        of this function are the same as the ones for the constructor of the
+        :class:`Module` class and will override the values of the module if
+        provided.
+        """
+        options.setdefault('url_prefix', module.url_prefix)
+        state = _ModuleSetupState(self, **options)
+        for func in module._register_events:
+            func(state)
+
+    def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
+        """Connects a URL rule.  Works exactly like the :meth:`route`
+        decorator.  If a view_func is provided it will be registered with the
+        endpoint.
+
+        Basically this example::
+
+            @app.route('/')
+            def index():
+                pass
+
+        Is equivalent to the following::
+
+            def index():
+                pass
+            app.add_url_rule('/', 'index', index)
+
+        If the view_func is not provided you will need to connect the endpoint
+        to a view function like so::
+
+            app.view_functions['index'] = index
+
+        .. versionchanged:: 0.2
+           `view_func` parameter added.
+
+        :param rule: the URL rule as string
+        :param endpoint: the endpoint for the registered URL rule.  Flask
+                         itself assumes the name of the view function as
+                         endpoint
+        :param view_func: the function to call when serving a request to the
+                          provided endpoint
+        :param options: the options to be forwarded to the underlying
+                        :class:`~werkzeug.routing.Rule` object
+        """
+        if endpoint is None:
+            assert view_func is not None, 'expected view func if endpoint ' \
+                                          'is not provided.'
+            endpoint = view_func.__name__
+        options['endpoint'] = endpoint
+        options.setdefault('methods', ('GET',))
+        self.url_map.add(Rule(rule, **options))
+        if view_func is not None:
+            self.view_functions[endpoint] = view_func
+
+    def route(self, rule, **options):
+        """A decorator that is used to register a view function for a
+        given URL rule.  Example::
+
+            @app.route('/')
+            def index():
+                return 'Hello World'
+
+        Variables parts in the route can be specified with angular
+        brackets (``/user/<username>``).  By default a variable part
+        in the URL accepts any string without a slash however a different
+        converter can be specified as well by using ``<converter:name>``.
+
+        Variable parts are passed to the view function as keyword
+        arguments.
+
+        The following converters are possible:
+
+        =========== ===========================================
+        `int`       accepts integers
+        `float`     like `int` but for floating point values
+        `path`      like the default but also accepts slashes
+        =========== ===========================================
+
+        Here some examples::
+
+            @app.route('/')
+            def index():
+                pass
+
+            @app.route('/<username>')
+            def show_user(username):
+                pass
+
+            @app.route('/post/<int:post_id>')
+            def show_post(post_id):
+                pass
+
+        An important detail to keep in mind is how Flask deals with trailing
+        slashes.  The idea is to keep each URL unique so the following rules
+        apply:
+
+        1. If a rule ends with a slash and is requested without a slash
+           by the user, the user is automatically redirected to the same
+           page with a trailing slash attached.
+        2. If a rule does not end with a trailing slash and the user request
+           the page with a trailing slash, a 404 not found is raised.
+
+        This is consistent with how web servers deal with static files.  This
+        also makes it possible to use relative link targets safely.
+
+        The :meth:`route` decorator accepts a couple of other arguments
+        as well:
+
+        :param rule: the URL rule as string
+        :param methods: a list of methods this rule should be limited
+                        to (``GET``, ``POST`` etc.).  By default a rule
+                        just listens for ``GET`` (and implicitly ``HEAD``).
+        :param subdomain: specifies the rule for the subdoain in case
+                          subdomain matching is in use.
+        :param strict_slashes: can be used to disable the strict slashes
+                               setting for this rule.  See above.
+        :param options: other options to be forwarded to the underlying
+                        :class:`~werkzeug.routing.Rule` object.
+        """
+        def decorator(f):
+            self.add_url_rule(rule, None, f, **options)
+            return f
+        return decorator
+
+    def errorhandler(self, code):
+        """A decorator that is used to register a function give a given
+        error code.  Example::
+
+            @app.errorhandler(404)
+            def page_not_found(error):
+                return 'This page does not exist', 404
+
+        You can also register a function as error handler without using
+        the :meth:`errorhandler` decorator.  The following example is
+        equivalent to the one above::
+
+            def page_not_found(error):
+                return 'This page does not exist', 404
+            app.error_handlers[404] = page_not_found
+
+        :param code: the code as integer for the handler
+        """
+        def decorator(f):
+            self.error_handlers[code] = f
+            return f
+        return decorator
+
+    def template_filter(self, name=None):
+        """A decorator that is used to register custom template filter.
+        You can specify a name for the filter, otherwise the function
+        name will be used. Example::
+
+          @app.template_filter()
+          def reverse(s):
+              return s[::-1]
+
+        :param name: the optional name of the filter, otherwise the
+                     function name will be used.
+        """
+        def decorator(f):
+            self.jinja_env.filters[name or f.__name__] = f
+            return f
+        return decorator
+
+    def before_request(self, f):
+        """Registers a function to run before each request."""
+        self.before_request_funcs.setdefault(None, []).append(f)
+        return f
+
+    def after_request(self, f):
+        """Register a function to be run after each request."""
+        self.after_request_funcs.setdefault(None, []).append(f)
+        return f
+
+    def context_processor(self, f):
+        """Registers a template context processor function."""
+        self.template_context_processors[None].append(f)
+        return f
+
+    def handle_http_exception(self, e):
+        """Handles an HTTP exception.  By default this will invoke the
+        registered error handlers and fall back to returning the
+        exception as response.
+
+        .. versionadded: 0.3
+        """
+        handler = self.error_handlers.get(e.code)
+        if handler is None:
+            return e
+        return handler(e)
+
+    def handle_exception(self, e):
+        """Default exception handling that kicks in when an exception
+        occours that is not catched.  In debug mode the exception will
+        be re-raised immediately, otherwise it is logged and the handler
+        for a 500 internal server error is used.  If no such handler
+        exists, a default 500 internal server error message is displayed.
+
+        .. versionadded: 0.3
+        """
+        handler = self.error_handlers.get(500)
+        if self.debug:
+            raise
+        self.logger.exception('Exception on %s [%s]' % (
+            request.path,
+            request.method
+        ))
+        if handler is None:
+            return InternalServerError()
+        return handler(e)
+
+    def dispatch_request(self):
+        """Does the request dispatching.  Matches the URL and returns the
+        return value of the view or error handler.  This does not have to
+        be a response object.  In order to convert the return value to a
+        proper response object, call :func:`make_response`.
+        """
+        req = _request_ctx_stack.top.request
+        try:
+            if req.routing_exception is not None:
+                raise req.routing_exception
+            return self.view_functions[req.endpoint](**req.view_args)
+        except HTTPException, e:
+            return self.handle_http_exception(e)
+
+    def make_response(self, rv):
+        """Converts the return value from a view function to a real
+        response object that is an instance of :attr:`response_class`.
+
+        The following types are allowed for `rv`:
+
+        .. tabularcolumns:: |p{3.5cm}|p{9.5cm}|
+
+        ======================= ===========================================
+        :attr:`response_class`  the object is returned unchanged
+        :class:`str`            a response object is created with the
+                                string as body
+        :class:`unicode`        a response object is created with the
+                                string encoded to utf-8 as body
+        :class:`tuple`          the response object is created with the
+                                contents of the tuple as arguments
+        a WSGI function         the function is called as WSGI application
+                                and buffered as response object
+        ======================= ===========================================
+
+        :param rv: the return value from the view function
+        """
+        if rv is None:
+            raise ValueError('View function did not return a response')
+        if isinstance(rv, self.response_class):
+            return rv
+        if isinstance(rv, basestring):
+            return self.response_class(rv)
+        if isinstance(rv, tuple):
+            return self.response_class(*rv)
+        return self.response_class.force_type(rv, request.environ)
+
+    def preprocess_request(self):
+        """Called before the actual request dispatching and will
+        call every as :meth:`before_request` decorated function.
+        If any of these function returns a value it's handled as
+        if it was the return value from the view and further
+        request handling is stopped.
+        """
+        funcs = self.before_request_funcs.get(None, ())
+        mod = request.module
+        if mod and mod in self.before_request_funcs:
+            funcs = chain(funcs, self.before_request_funcs[mod])
+        for func in funcs:
+            rv = func()
+            if rv is not None:
+                return rv
+
+    def process_response(self, response):
+        """Can be overridden in order to modify the response object
+        before it's sent to the WSGI server.  By default this will
+        call all the :meth:`after_request` decorated functions.
+
+        :param response: a :attr:`response_class` object.
+        :return: a new response object or the same, has to be an
+                 instance of :attr:`response_class`.
+        """
+        ctx = _request_ctx_stack.top
+        mod = ctx.request.module
+        if not isinstance(ctx.session, _NullSession):
+            self.save_session(ctx.session, response)
+        funcs = ()
+        if mod and mod in self.after_request_funcs:
+            funcs = chain(funcs, self.after_request_funcs[mod])
+        if None in self.after_request_funcs:
+            funcs = chain(funcs, self.after_request_funcs[None])
+        for handler in funcs:
+            response = handler(response)
+        return response
+
+    def wsgi_app(self, environ, start_response):
+        """The actual WSGI application.  This is not implemented in
+        `__call__` so that middlewares can be applied without losing a
+        reference to the class.  So instead of doing this::
+
+            app = MyMiddleware(app)
+
+        It's a better idea to do this instead::
+
+            app.wsgi_app = MyMiddleware(app.wsgi_app)
+
+        Then you still have the original application object around and
+        can continue to call methods on it.
+
+        .. versionchanged:: 0.4
+           The :meth:`after_request` functions are now called even if an
+           error handler took over request processing.  This ensures that
+           even if an exception happens database have the chance to
+           properly close the connection.
+
+        :param environ: a WSGI environment
+        :param start_response: a callable accepting a status code,
+                               a list of headers and an optional
+                               exception context to start the response
+        """
+        with self.request_context(environ):
+            try:
+                rv = self.preprocess_request()
+                if rv is None:
+                    rv = self.dispatch_request()
+                response = self.make_response(rv)
+            except Exception, e:
+                response = self.make_response(self.handle_exception(e))
+            try:
+                response = self.process_response(response)
+            except Exception, e:
+                response = self.make_response(self.handle_exception(e))
+            return response(environ, start_response)
+
+    def request_context(self, environ):
+        """Creates a request context from the given environment and binds
+        it to the current context.  This must be used in combination with
+        the `with` statement because the request is only bound to the
+        current context for the duration of the `with` block.
+
+        Example usage::
+
+            with app.request_context(environ):
+                do_something_with(request)
+
+        The object returned can also be used without the `with` statement
+        which is useful for working in the shell.  The example above is
+        doing exactly the same as this code::
+
+            ctx = app.request_context(environ)
+            ctx.push()
+            try:
+                do_something_with(request)
+            finally:
+                ctx.pop()
+
+        The big advantage of this approach is that you can use it without
+        the try/finally statement in a shell for interactive testing:
+
+        >>> ctx = app.test_request_context()
+        >>> ctx.bind()
+        >>> request.path
+        u'/'
+        >>> ctx.unbind()
+
+        .. versionchanged:: 0.3
+           Added support for non-with statement usage and `with` statement
+           is now passed the ctx object.
+
+        :param environ: a WSGI environment
+        """
+        return _RequestContext(self, environ)
+
+    def test_request_context(self, *args, **kwargs):
+        """Creates a WSGI environment from the given values (see
+        :func:`werkzeug.create_environ` for more information, this
+        function accepts the same arguments).
+        """
+        return self.request_context(create_environ(*args, **kwargs))
+
+    def __call__(self, environ, start_response):
+        """Shortcut for :attr:`wsgi_app`."""
+        return self.wsgi_app(environ, start_response)
+
+
+# context locals
+_request_ctx_stack = LocalStack()
+current_app = LocalProxy(lambda: _request_ctx_stack.top.app)
+request = LocalProxy(lambda: _request_ctx_stack.top.request)
+session = LocalProxy(lambda: _request_ctx_stack.top.session)
+g = LocalProxy(lambda: _request_ctx_stack.top.g)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/setup.cfg	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,6 @@
+[egg_info]
+tag_build = dev
+tag_date = true
+
+[aliases]
+release = egg_info -RDb ''
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bundled/flask/setup.py	Fri Jun 11 20:12:23 2010 -0400
@@ -0,0 +1,79 @@
+"""
+Flask
+-----
+
+Flask is a microframework for Python based on Werkzeug, Jinja 2 and good
+intentions. And before you ask: It's BSD licensed!
+
+Flask is Fun
+````````````
+
+::
+
+    from flask import Flask
+    app = Flask(__name__)
+
+    @app.route("/")
+    def hello():
+        return "Hello World!"
+
+    if __name__ == "__main__":
+        app.run()
+
+And Easy to Setup
+`````````````````
+
+::
+
+    $ easy_install Flask
+    $ python hello.py
+     * Running on http://localhost:5000/
+
+Links
+`````
+
+* `website <http://flask.pocoo.org/>`_
+* `documentation <http://flask.pocoo.org/docs/>`_
+* `development version
+  <http://github.com/mitsuhiko/flask/zipball/master#egg=Flask-dev>`_
+
+"""
+from setuptools import setup
+
+
+def run_tests():
+    import os, sys
+    sys.path.append(os.path.join(os.path.dirname(__file__), 'tests'))
+    from flask_tests import suite
+    return suite()
+
+
+setup(
+    name='Flask',
+    version='0.4',
+    url='http://github.com/mitsuhiko/flask/',
+    license='BSD',
+    author='Armin Ronacher',
+    author_email='armin.ronacher@active-4.com',
+    description='A microframework based on Werkzeug, Jinja2 '
+                'and good intentions',
+    long_description=__doc__,
+    py_modules=['flask'],
+    zip_safe=False,
+    platforms='any',
+    install_requires=[
+        'Werkzeug>=0.6.1',
+        'Jinja2>=2.4'
+    ],
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: OS Independent',
+        'Programming Language :: Python',
+        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+        'Topic :: Software Development :: Libraries :: Python Modules'
+    ],
+    test_suite='__main__.run_tests'
+)