--- /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)