Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/creactiweb/_templates/lib/flask/app.py
diff options
context:
space:
mode:
Diffstat (limited to 'creactiweb/_templates/lib/flask/app.py')
-rw-r--r--creactiweb/_templates/lib/flask/app.py948
1 files changed, 948 insertions, 0 deletions
diff --git a/creactiweb/_templates/lib/flask/app.py b/creactiweb/_templates/lib/flask/app.py
new file mode 100644
index 0000000..448df8f
--- /dev/null
+++ b/creactiweb/_templates/lib/flask/app.py
@@ -0,0 +1,948 @@
+# -*- coding: utf-8 -*-
+"""
+ flask.app
+ ~~~~~~~~~
+
+ This module implements the central WSGI application object.
+
+ :copyright: (c) 2010 by Armin Ronacher.
+ :license: BSD, see LICENSE for more details.
+"""
+
+from __future__ import with_statement
+
+from threading import Lock
+from datetime import timedelta, datetime
+from itertools import chain
+
+from jinja2 import Environment
+
+from werkzeug import ImmutableDict
+from werkzeug.routing import Map, Rule
+from werkzeug.exceptions import HTTPException, InternalServerError, \
+ MethodNotAllowed
+
+from .helpers import _PackageBoundObject, url_for, get_flashed_messages, \
+ _tojson_filter, _endpoint_from_view_func
+from .wrappers import Request, Response
+from .config import ConfigAttribute, Config
+from .ctx import _RequestContext
+from .globals import _request_ctx_stack, request
+from .session import Session, _NullSession
+from .module import _ModuleSetupState
+from .templating import _DispatchingJinjaLoader, \
+ _default_template_ctx_processor
+from .signals import request_started, request_finished, got_request_exception
+
+# a lock used for logger initialization
+_logger_lock = Lock()
+
+
+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__)
+
+ .. admonition:: About the First Parameter
+
+ The idea of the first parameter is to give Flask an idea what
+ belongs to your application. This name is used to find resources
+ on the file system, can be used by extensions to improve debugging
+ information and a lot more.
+
+ So it's important what you provide there. If you are using a single
+ module, `__name__` is always the correct value. If you however are
+ using a package, it's usually recommended to hardcode the name of
+ your package there.
+
+ For example if your application is defined in `yourapplication/app.py`
+ you should create it with one of the two versions below::
+
+ app = Flask('yourapplication')
+ app = Flask(__name__.split('.')[0])
+
+ Why is that? The application will work even with `__name__`, thanks
+ to how resources are looked up. However it will make debugging more
+ painful. Certain extensions can make assumptions based on the
+ import name of your application. For example the Flask-SQLAlchemy
+ extension will look for the code in your application that triggered
+ an SQL query in debug mode. If the import name is not properly set
+ up, that debugging information is lost. (For example it would only
+ pick up SQL queries in `yourapplicaiton.app` and not
+ `yourapplication.views.frontend`)
+
+ .. versionadded:: 0.5
+ The `static_path` parameter was added.
+
+ :param import_name: the name of the application package
+ :param static_path: can be used to specify a different path for the
+ static files on the web. Defaults to ``/static``.
+ This does not affect the folder the files are served
+ *from*.
+ """
+
+ #: 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.
+ #:
+ #: This is the default used for application and modules unless a
+ #: different value is passed to the constructor.
+ 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(
+ extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_']
+ )
+
+ #: Default configuration parameters.
+ default_config = ImmutableDict({
+ 'DEBUG': False,
+ 'TESTING': False,
+ 'PROPAGATE_EXCEPTIONS': None,
+ 'SECRET_KEY': None,
+ 'SESSION_COOKIE_NAME': 'session',
+ 'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
+ 'USE_X_SENDFILE': False,
+ 'LOGGER_NAME': None,
+ 'SERVER_NAME': None,
+ 'MAX_CONTENT_LENGTH': None
+ })
+
+ #: the test client that is used with when `test_client` is used.
+ #:
+ #: .. versionadded:: 0.7
+ test_client_class = None
+
+ def __init__(self, import_name, static_path=None):
+ _PackageBoundObject.__init__(self, import_name)
+ if static_path is not None:
+ self.static_path = static_path
+
+ #: 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:`after_request` decorator.
+ self.after_request_funcs = {}
+
+ #: A dictionary with list of functions that are called without argument
+ #: to populate the template context. The 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]
+ }
+
+ #: all the loaded modules in a dictionary by name.
+ #:
+ #: .. versionadded:: 0.5
+ self.modules = {}
+
+ #: a place where extensions can store application specific state. For
+ #: example this is where an extension could store database engines and
+ #: similar things. For backwards compatibility extensions should register
+ #: themselves like this::
+ #:
+ #: if not hasattr(app, 'extensions'):
+ #: app.extensions = {}
+ #: app.extensions['extensionname'] = SomeObject()
+ #:
+ #: The key must match the name of the `flaskext` module. For example in
+ #: case of a "Flask-Foo" extension in `flaskext.foo`, the key would be
+ #: ``'foo'``.
+ #:
+ #: .. versionadded:: 0.7
+ self.extensions = {}
+
+ #: 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.routing 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()
+
+ # register the static folder for the application. Do that even
+ # if the folder does not exist. First of all it might be created
+ # while the server is running (usually happens during development)
+ # but also because google appengine stores static files somewhere
+ # else when mapped with the .yml file.
+ self.add_url_rule(self.static_path + '/<path:filename>',
+ endpoint='static',
+ view_func=self.send_static_file)
+
+ #: The Jinja2 environment. It is created from the
+ #: :attr:`jinja_options`.
+ self.jinja_env = self.create_jinja_environment()
+ self.init_jinja_globals()
+
+ @property
+ def propagate_exceptions(self):
+ """Returns the value of the `PROPAGATE_EXCEPTIONS` configuration
+ value in case it's set, otherwise a sensible default is returned.
+
+ .. versionadded:: 0.7
+ """
+ rv = self.config['PROPAGATE_EXCEPTIONS']
+ if rv is not None:
+ return rv
+ return self.testing or self.debug
+
+ @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 flask.logging import create_logger
+ self._logger = rv = create_logger(self)
+ return rv
+
+ def create_jinja_environment(self):
+ """Creates the Jinja2 environment based on :attr:`jinja_options`
+ and :meth:`select_jinja_autoescape`.
+
+ .. versionadded:: 0.5
+ """
+ options = dict(self.jinja_options)
+ if 'autoescape' not in options:
+ options['autoescape'] = self.select_jinja_autoescape
+ return Environment(loader=_DispatchingJinjaLoader(self), **options)
+
+ def init_jinja_globals(self):
+ """Called directly after the environment was created to inject
+ some defaults (like `url_for`, `get_flashed_messages` and the
+ `tojson` filter.
+
+ .. versionadded:: 0.5
+ """
+ self.jinja_env.globals.update(
+ url_for=url_for,
+ get_flashed_messages=get_flashed_messages
+ )
+ self.jinja_env.filters['tojson'] = _tojson_filter
+
+ def select_jinja_autoescape(self, filename):
+ """Returns `True` if autoescaping should be active for the given
+ template name.
+
+ .. versionadded:: 0.5
+ """
+ if filename is None:
+ return False
+ return filename.endswith(('.html', '.htm', '.xml', '.xhtml'))
+
+ def update_template_context(self, context):
+ """Update the template context with some commonly used variables.
+ This injects request, session, config and g into the template
+ context as well as everything template context processors want
+ to inject. Note that the as of Flask 0.6, the original values
+ in the context will not be overriden if a context processor
+ decides to return a value with the same key.
+
+ :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])
+ orig_ctx = context.copy()
+ for func in funcs:
+ context.update(func())
+ # make sure the original values win. This makes it possible to
+ # easier add new variables in context processors without breaking
+ # existing views.
+ context.update(orig_ctx)
+
+ 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.
+
+ If you want to run the application in debug mode, but disable the
+ code execution on the interactive debugger, you can pass
+ ``use_evalex=False`` as parameter. This will keep the debugger's
+ traceback screen active, but disable code execution.
+
+ .. admonition:: Keep in Mind
+
+ Flask will suppress any server error with a generic error page
+ unless it is in debug mode. As such to enable just the
+ interactive debugger without the code reloading, you have to
+ invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``.
+ Setting ``use_debugger`` to `True` without being in debug mode
+ won't catch any exceptions because there won't be any to
+ catch.
+
+ :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, use_cookies=True):
+ """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.
+
+ .. versionadded:: 0.7
+ The `use_cookies` parameter was added as well as the ability
+ to override the client to be used by setting the
+ :attr:`test_client_class` attribute.
+ """
+ cls = self.test_client_class
+ if cls is None:
+ from flask.testing import FlaskClient as cls
+ return cls(self, self.response_class, use_cookies=use_cookies)
+
+ 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 = domain = None
+ if session.permanent:
+ expires = datetime.utcnow() + self.permanent_session_lifetime
+ if self.config['SERVER_NAME'] is not None:
+ domain = '.' + self.config['SERVER_NAME']
+ session.save_cookie(response, self.session_cookie_name,
+ expires=expires, httponly=True, domain=domain)
+
+ 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)
+ options.setdefault('subdomain', module.subdomain)
+ 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.
+
+ .. versionchanged:: 0.6
+ `OPTIONS` is added automatically as method.
+
+ :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. A change
+ to Werkzeug is handling of method options. methods
+ is a list of methods this rule should be limited
+ to (`GET`, `POST` etc.). By default a rule
+ just listens for `GET` (and implicitly `HEAD`).
+ Starting with Flask 0.6, `OPTIONS` is implicitly
+ added and handled by the standard request handling.
+ """
+ if endpoint is None:
+ endpoint = _endpoint_from_view_func(view_func)
+ options['endpoint'] = endpoint
+ methods = options.pop('methods', ('GET',))
+ provide_automatic_options = False
+ if 'OPTIONS' not in methods:
+ methods = tuple(methods) + ('OPTIONS',)
+ provide_automatic_options = True
+ rule = Rule(rule, methods=methods, **options)
+ rule.provide_automatic_options = provide_automatic_options
+ self.url_map.add(rule)
+ 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`).
+ Starting with Flask 0.6, `OPTIONS` is implicitly
+ added and handled by the standard request handling.
+ :param subdomain: specifies the rule for the subdomain 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
+ """
+ got_request_exception.send(self, exception=e)
+ handler = self.error_handlers.get(500)
+ if self.propagate_exceptions:
+ 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
+ rule = req.url_rule
+ # if we provide automatic options for this URL and the
+ # request came with the OPTIONS method, reply automatically
+ if getattr(rule, 'provide_automatic_options', False) \
+ and req.method == 'OPTIONS':
+ return self.make_default_options_response()
+ # otherwise dispatch to the handler for that endpoint
+ return self.view_functions[rule.endpoint](**req.view_args)
+ except HTTPException, e:
+ return self.handle_http_exception(e)
+
+ def make_default_options_response(self):
+ """This method is called to create the default `OPTIONS` response.
+ This can be changed through subclassing to change the default
+ behaviour of `OPTIONS` responses.
+
+ .. versionadded:: 0.7
+ """
+ # This would be nicer in Werkzeug 0.7, which however currently
+ # is not released. Werkzeug 0.7 provides a method called
+ # allowed_methods() that returns all methods that are valid for
+ # a given path.
+ methods = []
+ try:
+ _request_ctx_stack.top.url_adapter.match(method='--')
+ except MethodNotAllowed, e:
+ methods = e.valid_methods
+ except HTTPException, e:
+ pass
+ rv = self.response_class()
+ rv.allow.update(methods)
+ return rv
+
+ 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 create_url_adapter(self, request):
+ """Creates a URL adapter for the given request. The URL adapter
+ is created at a point where the request context is not yet set up
+ so the request is passed explicitly.
+
+ .. versionadded:: 0.6
+ """
+ return self.url_map.bind_to_environ(request.environ,
+ server_name=self.config['SERVER_NAME'])
+
+ 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.
+
+ .. versionchanged:: 0.5
+ As of Flask 0.5 the functions registered for after request
+ execution are called in reverse order of registration.
+
+ :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 = reversed(self.after_request_funcs[mod])
+ if None in self.after_request_funcs:
+ funcs = chain(funcs, reversed(self.after_request_funcs[None]))
+ for handler in funcs:
+ response = handler(response)
+ return 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).
+ """
+ from werkzeug import create_environ
+ environ_overrides = kwargs.setdefault('environ_overrides', {})
+ if self.config.get('SERVER_NAME'):
+ server_name = self.config.get('SERVER_NAME')
+ if ':' not in server_name:
+ http_host, http_port = server_name, '80'
+ else:
+ http_host, http_port = server_name.split(':', 1)
+
+ environ_overrides.setdefault('SERVER_NAME', server_name)
+ environ_overrides.setdefault('HTTP_HOST', server_name)
+ environ_overrides.setdefault('SERVER_PORT', http_port)
+ return self.request_context(create_environ(*args, **kwargs))
+
+ 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:
+ request_started.send(self)
+ 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))
+ request_finished.send(self, response=response)
+ return response(environ, start_response)
+
+ def __call__(self, environ, start_response):
+ """Shortcut for :attr:`wsgi_app`."""
+ return self.wsgi_app(environ, start_response)