diff --git a/docs/Makefile b/docs/Makefile
index 92dd33a1..d0c3cbf1 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -6,7 +6,7 @@
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
-BUILDDIR = _build
+BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
diff --git a/docs/api.rst b/docs/api.rst
deleted file mode 100644
index 1aa8048f..00000000
--- a/docs/api.rst
+++ /dev/null
@@ -1,717 +0,0 @@
-API
-===
-
-.. module:: flask
-
-This part of the documentation covers all the interfaces of Flask. For
-parts where Flask depends on external libraries, we document the most
-important right here and provide links to the canonical documentation.
-
-
-Application Object
-------------------
-
-.. autoclass:: Flask
- :members:
- :inherited-members:
-
-
-Blueprint Objects
------------------
-
-.. autoclass:: Blueprint
- :members:
- :inherited-members:
-
-Incoming Request Data
----------------------
-
-.. autoclass:: Request
- :members:
- :inherited-members:
- :exclude-members: json_module
-
-.. attribute:: request
-
- To access incoming request data, you can use the global `request`
- object. Flask parses incoming request data for you and gives you
- access to it through that global object. Internally Flask makes
- sure that you always get the correct data for the active thread if you
- are in a multithreaded environment.
-
- This is a proxy. See :ref:`notes-on-proxies` for more information.
-
- The request object is an instance of a :class:`~flask.Request`.
-
-
-Response Objects
-----------------
-
-.. autoclass:: flask.Response
- :members:
- :inherited-members:
- :exclude-members: json_module
-
-Sessions
---------
-
-If you have set :attr:`Flask.secret_key` (or configured it from
-:data:`SECRET_KEY`) you can use sessions in Flask applications. A session makes
-it possible to remember information from one request to another. The way Flask
-does this is by using a signed cookie. The user can look at the session
-contents, but can't modify it unless they know the secret key, so make sure to
-set that to something complex and unguessable.
-
-To access the current session you can use the :class:`session` object:
-
-.. class:: session
-
- The session object works pretty much like an ordinary dict, with the
- difference that it keeps track of modifications.
-
- This is a proxy. See :ref:`notes-on-proxies` for more information.
-
- The following attributes are interesting:
-
- .. attribute:: new
-
- ``True`` if the session is new, ``False`` otherwise.
-
- .. attribute:: modified
-
- ``True`` if the session object detected a modification. Be advised
- that modifications on mutable structures are not picked up
- automatically, in that situation you have to explicitly set the
- attribute to ``True`` yourself. Here an example::
-
- # this change is not picked up because a mutable object (here
- # a list) is changed.
- session['objects'].append(42)
- # so mark it as modified yourself
- session.modified = True
-
- .. attribute:: permanent
-
- If set to ``True`` the session lives for
- :attr:`~flask.Flask.permanent_session_lifetime` seconds. The
- default is 31 days. If set to ``False`` (which is the default) the
- session will be deleted when the user closes the browser.
-
-
-Session Interface
------------------
-
-.. versionadded:: 0.8
-
-The session interface provides a simple way to replace the session
-implementation that Flask is using.
-
-.. currentmodule:: flask.sessions
-
-.. autoclass:: SessionInterface
- :members:
-
-.. autoclass:: SecureCookieSessionInterface
- :members:
-
-.. autoclass:: SecureCookieSession
- :members:
-
-.. autoclass:: NullSession
- :members:
-
-.. autoclass:: SessionMixin
- :members:
-
-.. admonition:: Notice
-
- The :data:`PERMANENT_SESSION_LIFETIME` config can be an integer or ``timedelta``.
- The :attr:`~flask.Flask.permanent_session_lifetime` attribute is always a
- ``timedelta``.
-
-
-Test Client
------------
-
-.. currentmodule:: flask.testing
-
-.. autoclass:: FlaskClient
- :members:
-
-
-Test CLI Runner
----------------
-
-.. currentmodule:: flask.testing
-
-.. autoclass:: FlaskCliRunner
- :members:
-
-
-Application Globals
--------------------
-
-.. currentmodule:: flask
-
-To share data that is valid for one request only from one function to
-another, a global variable is not good enough because it would break in
-threaded environments. Flask provides you with a special object that
-ensures it is only valid for the active request and that will return
-different values for each request. In a nutshell: it does the right
-thing, like it does for :class:`request` and :class:`session`.
-
-.. data:: g
-
- A namespace object that can store data during an
- :doc:`application context `. This is an instance of
- :attr:`Flask.app_ctx_globals_class`, which defaults to
- :class:`ctx._AppCtxGlobals`.
-
- This is a good place to store resources during a request. For
- example, a ``before_request`` function could load a user object from
- a session id, then set ``g.user`` to be used in the view function.
-
- This is a proxy. See :ref:`notes-on-proxies` for more information.
-
- .. versionchanged:: 0.10
- Bound to the application context instead of the request context.
-
-.. autoclass:: flask.ctx._AppCtxGlobals
- :members:
-
-
-Useful Functions and Classes
-----------------------------
-
-.. data:: current_app
-
- A proxy to the application handling the current request. This is
- useful to access the application without needing to import it, or if
- it can't be imported, such as when using the application factory
- pattern or in blueprints and extensions.
-
- This is only available when an
- :doc:`application context ` is pushed. This happens
- automatically during requests and CLI commands. It can be controlled
- manually with :meth:`~flask.Flask.app_context`.
-
- This is a proxy. See :ref:`notes-on-proxies` for more information.
-
-.. autofunction:: has_request_context
-
-.. autofunction:: copy_current_request_context
-
-.. autofunction:: has_app_context
-
-.. autofunction:: url_for
-
-.. autofunction:: abort
-
-.. autofunction:: redirect
-
-.. autofunction:: make_response
-
-.. autofunction:: after_this_request
-
-.. autofunction:: send_file
-
-.. autofunction:: send_from_directory
-
-
-Message Flashing
-----------------
-
-.. autofunction:: flash
-
-.. autofunction:: get_flashed_messages
-
-
-JSON Support
-------------
-
-.. module:: flask.json
-
-Flask uses Python's built-in :mod:`json` module for handling JSON by
-default. The JSON implementation can be changed by assigning a different
-provider to :attr:`flask.Flask.json_provider_class` or
-:attr:`flask.Flask.json`. The functions provided by ``flask.json`` will
-use methods on ``app.json`` if an app context is active.
-
-Jinja's ``|tojson`` filter is configured to use the app's JSON provider.
-The filter marks the output with ``|safe``. Use it to render data inside
-HTML ``
-
-.. autofunction:: jsonify
-
-.. autofunction:: dumps
-
-.. autofunction:: dump
-
-.. autofunction:: loads
-
-.. autofunction:: load
-
-.. autoclass:: flask.json.provider.JSONProvider
- :members:
- :member-order: bysource
-
-.. autoclass:: flask.json.provider.DefaultJSONProvider
- :members:
- :member-order: bysource
-
-.. automodule:: flask.json.tag
-
-
-Template Rendering
-------------------
-
-.. currentmodule:: flask
-
-.. autofunction:: render_template
-
-.. autofunction:: render_template_string
-
-.. autofunction:: stream_template
-
-.. autofunction:: stream_template_string
-
-.. autofunction:: get_template_attribute
-
-Configuration
--------------
-
-.. autoclass:: Config
- :members:
-
-
-Stream Helpers
---------------
-
-.. autofunction:: stream_with_context
-
-Useful Internals
-----------------
-
-.. autoclass:: flask.ctx.RequestContext
- :members:
-
-.. data:: flask.globals.request_ctx
-
- The current :class:`~flask.ctx.RequestContext`. If a request context
- is not active, accessing attributes on this proxy will raise a
- ``RuntimeError``.
-
- This is an internal object that is essential to how Flask handles
- requests. Accessing this should not be needed in most cases. Most
- likely you want :data:`request` and :data:`session` instead.
-
-.. autoclass:: flask.ctx.AppContext
- :members:
-
-.. data:: flask.globals.app_ctx
-
- The current :class:`~flask.ctx.AppContext`. If an app context is not
- active, accessing attributes on this proxy will raise a
- ``RuntimeError``.
-
- This is an internal object that is essential to how Flask handles
- requests. Accessing this should not be needed in most cases. Most
- likely you want :data:`current_app` and :data:`g` instead.
-
-.. autoclass:: flask.blueprints.BlueprintSetupState
- :members:
-
-.. _core-signals-list:
-
-Signals
--------
-
-Signals are provided by the `Blinker`_ library. See :doc:`signals` for an introduction.
-
-.. _blinker: https://blinker.readthedocs.io/
-
-.. data:: template_rendered
-
- This signal is sent when a template was successfully rendered. The
- signal is invoked with the instance of the template as `template`
- and the context as dictionary (named `context`).
-
- Example subscriber::
-
- def log_template_renders(sender, template, context, **extra):
- sender.logger.debug('Rendering template "%s" with context %s',
- template.name or 'string template',
- context)
-
- from flask import template_rendered
- template_rendered.connect(log_template_renders, app)
-
-.. data:: flask.before_render_template
- :noindex:
-
- This signal is sent before template rendering process. The
- signal is invoked with the instance of the template as `template`
- and the context as dictionary (named `context`).
-
- Example subscriber::
-
- def log_template_renders(sender, template, context, **extra):
- sender.logger.debug('Rendering template "%s" with context %s',
- template.name or 'string template',
- context)
-
- from flask import before_render_template
- before_render_template.connect(log_template_renders, app)
-
-.. data:: request_started
-
- This signal is sent when the request context is set up, before
- any request processing happens. Because the request context is already
- bound, the subscriber can access the request with the standard global
- proxies such as :class:`~flask.request`.
-
- Example subscriber::
-
- def log_request(sender, **extra):
- sender.logger.debug('Request context is set up')
-
- from flask import request_started
- request_started.connect(log_request, app)
-
-.. data:: request_finished
-
- This signal is sent right before the response is sent to the client.
- It is passed the response to be sent named `response`.
-
- Example subscriber::
-
- def log_response(sender, response, **extra):
- sender.logger.debug('Request context is about to close down. '
- 'Response: %s', response)
-
- from flask import request_finished
- request_finished.connect(log_response, app)
-
-.. data:: got_request_exception
-
- This signal is sent when an unhandled exception happens during
- request processing, including when debugging. The exception is
- passed to the subscriber as ``exception``.
-
- This signal is not sent for
- :exc:`~werkzeug.exceptions.HTTPException`, or other exceptions that
- have error handlers registered, unless the exception was raised from
- an error handler.
-
- This example shows how to do some extra logging if a theoretical
- ``SecurityException`` was raised:
-
- .. code-block:: python
-
- from flask import got_request_exception
-
- def log_security_exception(sender, exception, **extra):
- if not isinstance(exception, SecurityException):
- return
-
- security_logger.exception(
- f"SecurityException at {request.url!r}",
- exc_info=exception,
- )
-
- got_request_exception.connect(log_security_exception, app)
-
-.. data:: request_tearing_down
-
- This signal is sent when the request is tearing down. This is always
- called, even if an exception is caused. Currently functions listening
- to this signal are called after the regular teardown handlers, but this
- is not something you can rely on.
-
- Example subscriber::
-
- def close_db_connection(sender, **extra):
- session.close()
-
- from flask import request_tearing_down
- request_tearing_down.connect(close_db_connection, app)
-
- As of Flask 0.9, this will also be passed an `exc` keyword argument
- that has a reference to the exception that caused the teardown if
- there was one.
-
-.. data:: appcontext_tearing_down
-
- This signal is sent when the app context is tearing down. This is always
- called, even if an exception is caused. Currently functions listening
- to this signal are called after the regular teardown handlers, but this
- is not something you can rely on.
-
- Example subscriber::
-
- def close_db_connection(sender, **extra):
- session.close()
-
- from flask import appcontext_tearing_down
- appcontext_tearing_down.connect(close_db_connection, app)
-
- This will also be passed an `exc` keyword argument that has a reference
- to the exception that caused the teardown if there was one.
-
-.. data:: appcontext_pushed
-
- This signal is sent when an application context is pushed. The sender
- is the application. This is usually useful for unittests in order to
- temporarily hook in information. For instance it can be used to
- set a resource early onto the `g` object.
-
- Example usage::
-
- from contextlib import contextmanager
- from flask import appcontext_pushed
-
- @contextmanager
- def user_set(app, user):
- def handler(sender, **kwargs):
- g.user = user
- with appcontext_pushed.connected_to(handler, app):
- yield
-
- And in the testcode::
-
- def test_user_me(self):
- with user_set(app, 'john'):
- c = app.test_client()
- resp = c.get('/users/me')
- assert resp.data == 'username=john'
-
- .. versionadded:: 0.10
-
-.. data:: appcontext_popped
-
- This signal is sent when an application context is popped. The sender
- is the application. This usually falls in line with the
- :data:`appcontext_tearing_down` signal.
-
- .. versionadded:: 0.10
-
-.. data:: message_flashed
-
- This signal is sent when the application is flashing a message. The
- messages is sent as `message` keyword argument and the category as
- `category`.
-
- Example subscriber::
-
- recorded = []
- def record(sender, message, category, **extra):
- recorded.append((message, category))
-
- from flask import message_flashed
- message_flashed.connect(record, app)
-
- .. versionadded:: 0.10
-
-
-Class-Based Views
------------------
-
-.. versionadded:: 0.7
-
-.. currentmodule:: None
-
-.. autoclass:: flask.views.View
- :members:
-
-.. autoclass:: flask.views.MethodView
- :members:
-
-.. _url-route-registrations:
-
-URL Route Registrations
------------------------
-
-Generally there are three ways to define rules for the routing system:
-
-1. You can use the :meth:`flask.Flask.route` decorator.
-2. You can use the :meth:`flask.Flask.add_url_rule` function.
-3. You can directly access the underlying Werkzeug routing system
- which is exposed as :attr:`flask.Flask.url_map`.
-
-Variable parts in the route can be specified with angular brackets
-(``/user/``). 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 ````.
-
-Variable parts are passed to the view function as keyword arguments.
-
-The following converters are available:
-
-=========== ===============================================
-`string` accepts any text without a slash (the default)
-`int` accepts integers
-`float` like `int` but for floating point values
-`path` like the default but also accepts slashes
-`any` matches one of the items provided
-`uuid` accepts UUID strings
-=========== ===============================================
-
-Custom converters can be defined using :attr:`flask.Flask.url_map`.
-
-Here are some examples::
-
- @app.route('/')
- def index():
- pass
-
- @app.route('/')
- def show_user(username):
- pass
-
- @app.route('/post/')
- 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 requests 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.
-
-You can also define multiple rules for the same function. They have to be
-unique however. Defaults can also be specified. Here for example is a
-definition for a URL that accepts an optional page::
-
- @app.route('/users/', defaults={'page': 1})
- @app.route('/users/page/')
- def show_users(page):
- pass
-
-This specifies that ``/users/`` will be the URL for page one and
-``/users/page/N`` will be the URL for page ``N``.
-
-If a URL contains a default value, it will be redirected to its simpler
-form with a 301 redirect. In the above example, ``/users/page/1`` will
-be redirected to ``/users/``. If your route handles ``GET`` and ``POST``
-requests, make sure the default route only handles ``GET``, as redirects
-can't preserve form data. ::
-
- @app.route('/region/', defaults={'id': 1})
- @app.route('/region/', methods=['GET', 'POST'])
- def region(id):
- pass
-
-Here are the parameters that :meth:`~flask.Flask.route` and
-:meth:`~flask.Flask.add_url_rule` accept. The only difference is that
-with the route parameter the view function is defined with the decorator
-instead of the `view_func` parameter.
-
-=============== ==========================================================
-`rule` the URL rule as string
-`endpoint` the endpoint for the registered URL rule. Flask itself
- assumes that the name of the view function is the name
- of the endpoint if not explicitly stated.
-`view_func` the function to call when serving a request to the
- provided endpoint. If this is not provided one can
- specify the function later by storing it in the
- :attr:`~flask.Flask.view_functions` dictionary with the
- endpoint as key.
-`defaults` A dictionary with defaults for this rule. See the
- example above for how defaults work.
-`subdomain` specifies the rule for the subdomain in case subdomain
- matching is in use. If not specified the default
- subdomain is assumed.
-`**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. They have to be specified as keyword arguments.
-=============== ==========================================================
-
-
-View Function Options
----------------------
-
-For internal usage the view functions can have some attributes attached to
-customize behavior the view function would normally not have control over.
-The following attributes can be provided optionally to either override
-some defaults to :meth:`~flask.Flask.add_url_rule` or general behavior:
-
-- `__name__`: The name of a function is by default used as endpoint. If
- endpoint is provided explicitly this value is used. Additionally this
- will be prefixed with the name of the blueprint by default which
- cannot be customized from the function itself.
-
-- `methods`: If methods are not provided when the URL rule is added,
- Flask will look on the view function object itself if a `methods`
- attribute exists. If it does, it will pull the information for the
- methods from there.
-
-- `provide_automatic_options`: if this attribute is set Flask will
- either force enable or disable the automatic implementation of the
- HTTP ``OPTIONS`` response. This can be useful when working with
- decorators that want to customize the ``OPTIONS`` response on a per-view
- basis.
-
-- `required_methods`: if this attribute is set, Flask will always add
- these methods when registering a URL rule even if the methods were
- explicitly overridden in the ``route()`` call.
-
-Full example::
-
- def index():
- if request.method == 'OPTIONS':
- # custom options handling here
- ...
- return 'Hello World!'
- index.provide_automatic_options = False
- index.methods = ['GET', 'OPTIONS']
-
- app.add_url_rule('/', index)
-
-.. versionadded:: 0.8
- The `provide_automatic_options` functionality was added.
-
-Command Line Interface
-----------------------
-
-.. currentmodule:: flask.cli
-
-.. autoclass:: FlaskGroup
- :members:
-
-.. autoclass:: AppGroup
- :members:
-
-.. autoclass:: ScriptInfo
- :members:
-
-.. autofunction:: load_dotenv
-
-.. autofunction:: with_appcontext
-
-.. autofunction:: pass_script_info
-
- Marks a function so that an instance of :class:`ScriptInfo` is passed
- as first argument to the click callback.
-
-.. autodata:: run_command
-
-.. autodata:: shell_command
diff --git a/docs/appcontext.rst b/docs/appcontext.rst
deleted file mode 100644
index 5509a9a7..00000000
--- a/docs/appcontext.rst
+++ /dev/null
@@ -1,147 +0,0 @@
-.. currentmodule:: flask
-
-The Application Context
-=======================
-
-The application context keeps track of the application-level data during
-a request, CLI command, or other activity. Rather than passing the
-application around to each function, the :data:`current_app` and
-:data:`g` proxies are accessed instead.
-
-This is similar to :doc:`/reqcontext`, which keeps track of
-request-level data during a request. A corresponding application context
-is pushed when a request context is pushed.
-
-Purpose of the Context
-----------------------
-
-The :class:`Flask` application object has attributes, such as
-:attr:`~Flask.config`, that are useful to access within views and
-:doc:`CLI commands `. However, importing the ``app`` instance
-within the modules in your project is prone to circular import issues.
-When using the :doc:`app factory pattern ` or
-writing reusable :doc:`blueprints ` or
-:doc:`extensions ` there won't be an ``app`` instance to
-import at all.
-
-Flask solves this issue with the *application context*. Rather than
-referring to an ``app`` directly, you use the :data:`current_app`
-proxy, which points to the application handling the current activity.
-
-Flask automatically *pushes* an application context when handling a
-request. View functions, error handlers, and other functions that run
-during a request will have access to :data:`current_app`.
-
-Flask will also automatically push an app context when running CLI
-commands registered with :attr:`Flask.cli` using ``@app.cli.command()``.
-
-
-Lifetime of the Context
------------------------
-
-The application context is created and destroyed as necessary. When a
-Flask application begins handling a request, it pushes an application
-context and a :doc:`request context `. When the request
-ends it pops the request context then the application context.
-Typically, an application context will have the same lifetime as a
-request.
-
-See :doc:`/reqcontext` for more information about how the contexts work
-and the full life cycle of a request.
-
-
-Manually Push a Context
------------------------
-
-If you try to access :data:`current_app`, or anything that uses it,
-outside an application context, you'll get this error message:
-
-.. code-block:: pytb
-
- RuntimeError: Working outside of application context.
-
- This typically means that you attempted to use functionality that
- needed to interface with the current application object in some way.
- To solve this, set up an application context with app.app_context().
-
-If you see that error while configuring your application, such as when
-initializing an extension, you can push a context manually since you
-have direct access to the ``app``. Use :meth:`~Flask.app_context` in a
-``with`` block, and everything that runs in the block will have access
-to :data:`current_app`. ::
-
- def create_app():
- app = Flask(__name__)
-
- with app.app_context():
- init_db()
-
- return app
-
-If you see that error somewhere else in your code not related to
-configuring the application, it most likely indicates that you should
-move that code into a view function or CLI command.
-
-
-Storing Data
-------------
-
-The application context is a good place to store common data during a
-request or CLI command. Flask provides the :data:`g object ` for this
-purpose. It is a simple namespace object that has the same lifetime as
-an application context.
-
-.. note::
- The ``g`` name stands for "global", but that is referring to the
- data being global *within a context*. The data on ``g`` is lost
- after the context ends, and it is not an appropriate place to store
- data between requests. Use the :data:`session` or a database to
- store data across requests.
-
-A common use for :data:`g` is to manage resources during a request.
-
-1. ``get_X()`` creates resource ``X`` if it does not exist, caching it
- as ``g.X``.
-2. ``teardown_X()`` closes or otherwise deallocates the resource if it
- exists. It is registered as a :meth:`~Flask.teardown_appcontext`
- handler.
-
-For example, you can manage a database connection using this pattern::
-
- from flask import g
-
- def get_db():
- if 'db' not in g:
- g.db = connect_to_database()
-
- return g.db
-
- @app.teardown_appcontext
- def teardown_db(exception):
- db = g.pop('db', None)
-
- if db is not None:
- db.close()
-
-During a request, every call to ``get_db()`` will return the same
-connection, and it will be closed automatically at the end of the
-request.
-
-You can use :class:`~werkzeug.local.LocalProxy` to make a new context
-local from ``get_db()``::
-
- from werkzeug.local import LocalProxy
- db = LocalProxy(get_db)
-
-Accessing ``db`` will call ``get_db`` internally, in the same way that
-:data:`current_app` works.
-
-
-Events and Signals
-------------------
-
-The application will call functions registered with :meth:`~Flask.teardown_appcontext`
-when the application context is popped.
-
-The following signals are sent: :data:`appcontext_pushed`,
-:data:`appcontext_tearing_down`, and :data:`appcontext_popped`.
diff --git a/docs/async-await.rst b/docs/async-await.rst
deleted file mode 100644
index 16b61945..00000000
--- a/docs/async-await.rst
+++ /dev/null
@@ -1,125 +0,0 @@
-.. _async_await:
-
-Using ``async`` and ``await``
-=============================
-
-.. versionadded:: 2.0
-
-Routes, error handlers, before request, after request, and teardown
-functions can all be coroutine functions if Flask is installed with the
-``async`` extra (``pip install flask[async]``). This allows views to be
-defined with ``async def`` and use ``await``.
-
-.. code-block:: python
-
- @app.route("/get-data")
- async def get_data():
- data = await async_db_query(...)
- return jsonify(data)
-
-Pluggable class-based views also support handlers that are implemented as
-coroutines. This applies to the :meth:`~flask.views.View.dispatch_request`
-method in views that inherit from the :class:`flask.views.View` class, as
-well as all the HTTP method handlers in views that inherit from the
-:class:`flask.views.MethodView` class.
-
-.. admonition:: Using ``async`` with greenlet
-
- When using gevent or eventlet to serve an application or patch the
- runtime, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is
- required.
-
-
-Performance
------------
-
-Async functions require an event loop to run. Flask, as a WSGI
-application, uses one worker to handle one request/response cycle.
-When a request comes in to an async view, Flask will start an event loop
-in a thread, run the view function there, then return the result.
-
-Each request still ties up one worker, even for async views. The upside
-is that you can run async code within a view, for example to make
-multiple concurrent database queries, HTTP requests to an external API,
-etc. However, the number of requests your application can handle at one
-time will remain the same.
-
-**Async is not inherently faster than sync code.** Async is beneficial
-when performing concurrent IO-bound tasks, but will probably not improve
-CPU-bound tasks. Traditional Flask views will still be appropriate for
-most use cases, but Flask's async support enables writing and using
-code that wasn't possible natively before.
-
-
-Background tasks
-----------------
-
-Async functions will run in an event loop until they complete, at
-which stage the event loop will stop. This means any additional
-spawned tasks that haven't completed when the async function completes
-will be cancelled. Therefore you cannot spawn background tasks, for
-example via ``asyncio.create_task``.
-
-If you wish to use background tasks it is best to use a task queue to
-trigger background work, rather than spawn tasks in a view
-function. With that in mind you can spawn asyncio tasks by serving
-Flask with an ASGI server and utilising the asgiref WsgiToAsgi adapter
-as described in :doc:`deploying/asgi`. This works as the adapter creates
-an event loop that runs continually.
-
-
-When to use Quart instead
--------------------------
-
-Flask's async support is less performant than async-first frameworks due
-to the way it is implemented. If you have a mainly async codebase it
-would make sense to consider `Quart`_. Quart is a reimplementation of
-Flask based on the `ASGI`_ standard instead of WSGI. This allows it to
-handle many concurrent requests, long running requests, and websockets
-without requiring multiple worker processes or threads.
-
-It has also already been possible to run Flask with Gevent or Eventlet
-to get many of the benefits of async request handling. These libraries
-patch low-level Python functions to accomplish this, whereas ``async``/
-``await`` and ASGI use standard, modern Python capabilities. Deciding
-whether you should use Flask, Quart, or something else is ultimately up
-to understanding the specific needs of your project.
-
-.. _Quart: https://github.com/pallets/quart
-.. _ASGI: https://asgi.readthedocs.io/en/latest/
-
-
-Extensions
-----------
-
-Flask extensions predating Flask's async support do not expect async views.
-If they provide decorators to add functionality to views, those will probably
-not work with async views because they will not await the function or be
-awaitable. Other functions they provide will not be awaitable either and
-will probably be blocking if called within an async view.
-
-Extension authors can support async functions by utilising the
-:meth:`flask.Flask.ensure_sync` method. For example, if the extension
-provides a view function decorator add ``ensure_sync`` before calling
-the decorated function,
-
-.. code-block:: python
-
- def extension(func):
- @wraps(func)
- def wrapper(*args, **kwargs):
- ... # Extension logic
- return current_app.ensure_sync(func)(*args, **kwargs)
-
- return wrapper
-
-Check the changelog of the extension you want to use to see if they've
-implemented async support, or make a feature request or PR to them.
-
-
-Other event loops
------------------
-
-At the moment Flask only supports :mod:`asyncio`. It's possible to
-override :meth:`flask.Flask.ensure_sync` to change how async functions
-are wrapped to use a different library.
diff --git a/docs/blueprints.rst b/docs/blueprints.rst
deleted file mode 100644
index d5cf3d82..00000000
--- a/docs/blueprints.rst
+++ /dev/null
@@ -1,315 +0,0 @@
-Modular Applications with Blueprints
-====================================
-
-.. currentmodule:: flask
-
-.. versionadded:: 0.7
-
-Flask uses a concept of *blueprints* for making application components and
-supporting common patterns within an application or across applications.
-Blueprints can greatly simplify how large applications work and provide a
-central means for Flask extensions to register operations on applications.
-A :class:`Blueprint` object works similarly to a :class:`Flask`
-application object, but it is not actually an application. Rather it is a
-*blueprint* of how to construct or extend an application.
-
-Why Blueprints?
----------------
-
-Blueprints in Flask are intended for these cases:
-
-* Factor an application into a set of blueprints. This is ideal for
- larger applications; a project could instantiate an application object,
- initialize several extensions, and register a collection of blueprints.
-* Register a blueprint on an application at a URL prefix and/or subdomain.
- Parameters in the URL prefix/subdomain become common view arguments
- (with defaults) across all view functions in the blueprint.
-* Register a blueprint multiple times on an application with different URL
- rules.
-* Provide template filters, static files, templates, and other utilities
- through blueprints. A blueprint does not have to implement applications
- or view functions.
-* Register a blueprint on an application for any of these cases when
- initializing a Flask extension.
-
-A blueprint in Flask is not a pluggable app because it is not actually an
-application -- it's a set of operations which can be registered on an
-application, even multiple times. Why not have multiple application
-objects? You can do that (see :doc:`/patterns/appdispatch`), but your
-applications will have separate configs and will be managed at the WSGI
-layer.
-
-Blueprints instead provide separation at the Flask level, share
-application config, and can change an application object as necessary with
-being registered. The downside is that you cannot unregister a blueprint
-once an application was created without having to destroy the whole
-application object.
-
-The Concept of Blueprints
--------------------------
-
-The basic concept of blueprints is that they record operations to execute
-when registered on an application. Flask associates view functions with
-blueprints when dispatching requests and generating URLs from one endpoint
-to another.
-
-My First Blueprint
-------------------
-
-This is what a very basic blueprint looks like. In this case we want to
-implement a blueprint that does simple rendering of static templates::
-
- from flask import Blueprint, render_template, abort
- from jinja2 import TemplateNotFound
-
- simple_page = Blueprint('simple_page', __name__,
- template_folder='templates')
-
- @simple_page.route('/', defaults={'page': 'index'})
- @simple_page.route('/')
- def show(page):
- try:
- return render_template(f'pages/{page}.html')
- except TemplateNotFound:
- abort(404)
-
-When you bind a function with the help of the ``@simple_page.route``
-decorator, the blueprint will record the intention of registering the
-function ``show`` on the application when it's later registered.
-Additionally it will prefix the endpoint of the function with the
-name of the blueprint which was given to the :class:`Blueprint`
-constructor (in this case also ``simple_page``). The blueprint's name
-does not modify the URL, only the endpoint.
-
-Registering Blueprints
-----------------------
-
-So how do you register that blueprint? Like this::
-
- from flask import Flask
- from yourapplication.simple_page import simple_page
-
- app = Flask(__name__)
- app.register_blueprint(simple_page)
-
-If you check the rules registered on the application, you will find
-these::
-
- >>> app.url_map
- Map([' (HEAD, OPTIONS, GET) -> static>,
- ' (HEAD, OPTIONS, GET) -> simple_page.show>,
- simple_page.show>])
-
-The first one is obviously from the application itself for the static
-files. The other two are for the `show` function of the ``simple_page``
-blueprint. As you can see, they are also prefixed with the name of the
-blueprint and separated by a dot (``.``).
-
-Blueprints however can also be mounted at different locations::
-
- app.register_blueprint(simple_page, url_prefix='/pages')
-
-And sure enough, these are the generated rules::
-
- >>> app.url_map
- Map([' (HEAD, OPTIONS, GET) -> static>,
- ' (HEAD, OPTIONS, GET) -> simple_page.show>,
- simple_page.show>])
-
-On top of that you can register blueprints multiple times though not every
-blueprint might respond properly to that. In fact it depends on how the
-blueprint is implemented if it can be mounted more than once.
-
-Nesting Blueprints
-------------------
-
-It is possible to register a blueprint on another blueprint.
-
-.. code-block:: python
-
- parent = Blueprint('parent', __name__, url_prefix='/parent')
- child = Blueprint('child', __name__, url_prefix='/child')
- parent.register_blueprint(child)
- app.register_blueprint(parent)
-
-The child blueprint will gain the parent's name as a prefix to its
-name, and child URLs will be prefixed with the parent's URL prefix.
-
-.. code-block:: python
-
- url_for('parent.child.create')
- /parent/child/create
-
-In addition a child blueprint's will gain their parent's subdomain,
-with their subdomain as prefix if present i.e.
-
-.. code-block:: python
-
- parent = Blueprint('parent', __name__, subdomain='parent')
- child = Blueprint('child', __name__, subdomain='child')
- parent.register_blueprint(child)
- app.register_blueprint(parent)
-
- url_for('parent.child.create', _external=True)
- "child.parent.domain.tld"
-
-Blueprint-specific before request functions, etc. registered with the
-parent will trigger for the child. If a child does not have an error
-handler that can handle a given exception, the parent's will be tried.
-
-
-Blueprint Resources
--------------------
-
-Blueprints can provide resources as well. Sometimes you might want to
-introduce a blueprint only for the resources it provides.
-
-Blueprint Resource Folder
-`````````````````````````
-
-Like for regular applications, blueprints are considered to be contained
-in a folder. While multiple blueprints can originate from the same folder,
-it does not have to be the case and it's usually not recommended.
-
-The folder is inferred from the second argument to :class:`Blueprint` which
-is usually `__name__`. This argument specifies what logical Python
-module or package corresponds to the blueprint. If it points to an actual
-Python package that package (which is a folder on the filesystem) is the
-resource folder. If it's a module, the package the module is contained in
-will be the resource folder. You can access the
-:attr:`Blueprint.root_path` property to see what the resource folder is::
-
- >>> simple_page.root_path
- '/Users/username/TestProject/yourapplication'
-
-To quickly open sources from this folder you can use the
-:meth:`~Blueprint.open_resource` function::
-
- with simple_page.open_resource('static/style.css') as f:
- code = f.read()
-
-Static Files
-````````````
-
-A blueprint can expose a folder with static files by providing the path
-to the folder on the filesystem with the ``static_folder`` argument.
-It is either an absolute path or relative to the blueprint's location::
-
- admin = Blueprint('admin', __name__, static_folder='static')
-
-By default the rightmost part of the path is where it is exposed on the
-web. This can be changed with the ``static_url_path`` argument. Because the
-folder is called ``static`` here it will be available at the
-``url_prefix`` of the blueprint + ``/static``. If the blueprint
-has the prefix ``/admin``, the static URL will be ``/admin/static``.
-
-The endpoint is named ``blueprint_name.static``. You can generate URLs
-to it with :func:`url_for` like you would with the static folder of the
-application::
-
- url_for('admin.static', filename='style.css')
-
-However, if the blueprint does not have a ``url_prefix``, it is not
-possible to access the blueprint's static folder. This is because the
-URL would be ``/static`` in this case, and the application's ``/static``
-route takes precedence. Unlike template folders, blueprint static
-folders are not searched if the file does not exist in the application
-static folder.
-
-Templates
-`````````
-
-If you want the blueprint to expose templates you can do that by providing
-the `template_folder` parameter to the :class:`Blueprint` constructor::
-
- admin = Blueprint('admin', __name__, template_folder='templates')
-
-For static files, the path can be absolute or relative to the blueprint
-resource folder.
-
-The template folder is added to the search path of templates but with a lower
-priority than the actual application's template folder. That way you can
-easily override templates that a blueprint provides in the actual application.
-This also means that if you don't want a blueprint template to be accidentally
-overridden, make sure that no other blueprint or actual application template
-has the same relative path. When multiple blueprints provide the same relative
-template path the first blueprint registered takes precedence over the others.
-
-
-So if you have a blueprint in the folder ``yourapplication/admin`` and you
-want to render the template ``'admin/index.html'`` and you have provided
-``templates`` as a `template_folder` you will have to create a file like
-this: :file:`yourapplication/admin/templates/admin/index.html`. The reason
-for the extra ``admin`` folder is to avoid getting our template overridden
-by a template named ``index.html`` in the actual application template
-folder.
-
-To further reiterate this: if you have a blueprint named ``admin`` and you
-want to render a template called :file:`index.html` which is specific to this
-blueprint, the best idea is to lay out your templates like this::
-
- yourpackage/
- blueprints/
- admin/
- templates/
- admin/
- index.html
- __init__.py
-
-And then when you want to render the template, use :file:`admin/index.html` as
-the name to look up the template by. If you encounter problems loading
-the correct templates enable the ``EXPLAIN_TEMPLATE_LOADING`` config
-variable which will instruct Flask to print out the steps it goes through
-to locate templates on every ``render_template`` call.
-
-Building URLs
--------------
-
-If you want to link from one page to another you can use the
-:func:`url_for` function just like you normally would do just that you
-prefix the URL endpoint with the name of the blueprint and a dot (``.``)::
-
- url_for('admin.index')
-
-Additionally if you are in a view function of a blueprint or a rendered
-template and you want to link to another endpoint of the same blueprint,
-you can use relative redirects by prefixing the endpoint with a dot only::
-
- url_for('.index')
-
-This will link to ``admin.index`` for instance in case the current request
-was dispatched to any other admin blueprint endpoint.
-
-
-Blueprint Error Handlers
-------------------------
-
-Blueprints support the ``errorhandler`` decorator just like the :class:`Flask`
-application object, so it is easy to make Blueprint-specific custom error
-pages.
-
-Here is an example for a "404 Page Not Found" exception::
-
- @simple_page.errorhandler(404)
- def page_not_found(e):
- return render_template('pages/404.html')
-
-Most errorhandlers will simply work as expected; however, there is a caveat
-concerning handlers for 404 and 405 exceptions. These errorhandlers are only
-invoked from an appropriate ``raise`` statement or a call to ``abort`` in another
-of the blueprint's view functions; they are not invoked by, e.g., an invalid URL
-access. This is because the blueprint does not "own" a certain URL space, so
-the application instance has no way of knowing which blueprint error handler it
-should run if given an invalid URL. If you would like to execute different
-handling strategies for these errors based on URL prefixes, they may be defined
-at the application level using the ``request`` proxy object::
-
- @app.errorhandler(404)
- @app.errorhandler(405)
- def _handle_api_error(ex):
- if request.path.startswith('/api/'):
- return jsonify(error=str(ex)), ex.code
- else:
- return ex
-
-See :doc:`/errorhandling`.
diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle
new file mode 100644
index 00000000..cf5ce898
Binary files /dev/null and b/docs/build/doctrees/environment.pickle differ
diff --git a/docs/build/doctrees/flask.doctree b/docs/build/doctrees/flask.doctree
new file mode 100644
index 00000000..96358e9e
Binary files /dev/null and b/docs/build/doctrees/flask.doctree differ
diff --git a/docs/build/doctrees/flask.json.doctree b/docs/build/doctrees/flask.json.doctree
new file mode 100644
index 00000000..fad21093
Binary files /dev/null and b/docs/build/doctrees/flask.json.doctree differ
diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree
new file mode 100644
index 00000000..e5b77521
Binary files /dev/null and b/docs/build/doctrees/index.doctree differ
diff --git a/docs/build/doctrees/modules.doctree b/docs/build/doctrees/modules.doctree
new file mode 100644
index 00000000..f9947e42
Binary files /dev/null and b/docs/build/doctrees/modules.doctree differ
diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo
new file mode 100644
index 00000000..8a2d869b
--- /dev/null
+++ b/docs/build/html/.buildinfo
@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: 21a39fdf72bffce870db8834b83d0887
+tags: 645f666f9bcd5a90fca523b33c5a78b7
diff --git a/docs/build/html/_sources/flask.json.rst.txt b/docs/build/html/_sources/flask.json.rst.txt
new file mode 100644
index 00000000..1ed514ee
--- /dev/null
+++ b/docs/build/html/_sources/flask.json.rst.txt
@@ -0,0 +1,29 @@
+flask.json package
+==================
+
+Submodules
+----------
+
+flask.json.provider module
+--------------------------
+
+.. automodule:: flask.json.provider
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.json.tag module
+---------------------
+
+.. automodule:: flask.json.tag
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: flask.json
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/build/html/_sources/flask.rst.txt b/docs/build/html/_sources/flask.rst.txt
new file mode 100644
index 00000000..7ebba00b
--- /dev/null
+++ b/docs/build/html/_sources/flask.rst.txt
@@ -0,0 +1,149 @@
+flask package
+=============
+
+Subpackages
+-----------
+
+.. toctree::
+ :maxdepth: 4
+
+ flask.json
+
+Submodules
+----------
+
+flask.app module
+----------------
+
+.. automodule:: flask.app
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.blueprints module
+-----------------------
+
+.. automodule:: flask.blueprints
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.cli module
+----------------
+
+.. automodule:: flask.cli
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.config module
+-------------------
+
+.. automodule:: flask.config
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.ctx module
+----------------
+
+.. automodule:: flask.ctx
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.debughelpers module
+-------------------------
+
+.. automodule:: flask.debughelpers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.globals module
+--------------------
+
+.. automodule:: flask.globals
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.helpers module
+--------------------
+
+.. automodule:: flask.helpers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.logging module
+--------------------
+
+.. automodule:: flask.logging
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.sessions module
+---------------------
+
+.. automodule:: flask.sessions
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.signals module
+--------------------
+
+.. automodule:: flask.signals
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.templating module
+-----------------------
+
+.. automodule:: flask.templating
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.testing module
+--------------------
+
+.. automodule:: flask.testing
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.typing module
+-------------------
+
+.. automodule:: flask.typing
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.views module
+------------------
+
+.. automodule:: flask.views
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+flask.wrappers module
+---------------------
+
+.. automodule:: flask.wrappers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+Module contents
+---------------
+
+.. automodule:: flask
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt
new file mode 100644
index 00000000..bef08e80
--- /dev/null
+++ b/docs/build/html/_sources/index.rst.txt
@@ -0,0 +1,16 @@
+.. Flask documentation master file, created by
+ sphinx-quickstart on Thu Apr 10 19:53:46 2025.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Flask - Documentación Personalizada
+====================================
+
+Bienvenido a la documentación del proyecto Flask.
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contenido:
+
+ modules
+
diff --git a/docs/build/html/_sources/modules.rst.txt b/docs/build/html/_sources/modules.rst.txt
new file mode 100644
index 00000000..5823aac6
--- /dev/null
+++ b/docs/build/html/_sources/modules.rst.txt
@@ -0,0 +1,7 @@
+flask
+=====
+
+.. toctree::
+ :maxdepth: 4
+
+ flask
diff --git a/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js b/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js
new file mode 100644
index 00000000..81415803
--- /dev/null
+++ b/docs/build/html/_static/_sphinx_javascript_frameworks_compat.js
@@ -0,0 +1,123 @@
+/* Compatability shim for jQuery and underscores.js.
+ *
+ * Copyright Sphinx contributors
+ * Released under the two clause BSD licence
+ */
+
+/**
+ * small helper function to urldecode strings
+ *
+ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
+ */
+jQuery.urldecode = function(x) {
+ if (!x) {
+ return x
+ }
+ return decodeURIComponent(x.replace(/\+/g, ' '));
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+ if (typeof s === 'undefined')
+ s = document.location.search;
+ var parts = s.substr(s.indexOf('?') + 1).split('&');
+ var result = {};
+ for (var i = 0; i < parts.length; i++) {
+ var tmp = parts[i].split('=', 2);
+ var key = jQuery.urldecode(tmp[0]);
+ var value = jQuery.urldecode(tmp[1]);
+ if (key in result)
+ result[key].push(value);
+ else
+ result[key] = [value];
+ }
+ return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+ function highlight(node, addItems) {
+ if (node.nodeType === 3) {
+ var val = node.nodeValue;
+ var pos = val.toLowerCase().indexOf(text);
+ if (pos >= 0 &&
+ !jQuery(node.parentNode).hasClass(className) &&
+ !jQuery(node.parentNode).hasClass("nohighlight")) {
+ var span;
+ var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
+ if (isInSVG) {
+ span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
+ } else {
+ span = document.createElement("span");
+ span.className = className;
+ }
+ span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+ node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+ document.createTextNode(val.substr(pos + text.length)),
+ node.nextSibling));
+ node.nodeValue = val.substr(0, pos);
+ if (isInSVG) {
+ var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
+ var bbox = node.parentElement.getBBox();
+ rect.x.baseVal.value = bbox.x;
+ rect.y.baseVal.value = bbox.y;
+ rect.width.baseVal.value = bbox.width;
+ rect.height.baseVal.value = bbox.height;
+ rect.setAttribute('class', className);
+ addItems.push({
+ "parent": node.parentNode,
+ "target": rect});
+ }
+ }
+ }
+ else if (!jQuery(node).is("button, select, textarea")) {
+ jQuery.each(node.childNodes, function() {
+ highlight(this, addItems);
+ });
+ }
+ }
+ var addItems = [];
+ var result = this.each(function() {
+ highlight(this, addItems);
+ });
+ for (var i = 0; i < addItems.length; ++i) {
+ jQuery(addItems[i].parent).before(addItems[i].target);
+ }
+ return result;
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+ jQuery.uaMatch = function(ua) {
+ ua = ua.toLowerCase();
+
+ var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+ /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+ /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+ /(msie) ([\w.]+)/.exec(ua) ||
+ ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+ [];
+
+ return {
+ browser: match[ 1 ] || "",
+ version: match[ 2 ] || "0"
+ };
+ };
+ jQuery.browser = {};
+ jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css
new file mode 100644
index 00000000..7ebbd6d0
--- /dev/null
+++ b/docs/build/html/_static/basic.css
@@ -0,0 +1,914 @@
+/*
+ * Sphinx stylesheet -- basic theme.
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+ clear: both;
+}
+
+div.section::after {
+ display: block;
+ content: '';
+ clear: left;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+ width: 100%;
+ font-size: 90%;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+ padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+ float: left;
+ width: 230px;
+ margin-left: -100%;
+ font-size: 90%;
+ word-wrap: break-word;
+ overflow-wrap : break-word;
+}
+
+div.sphinxsidebar ul {
+ list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+ margin-left: 20px;
+ list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #98dbcc;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox form.search {
+ overflow: hidden;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+ float: left;
+ width: 80%;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+div.sphinxsidebar #searchbox input[type="submit"] {
+ float: left;
+ width: 20%;
+ border-left: none;
+ padding: 0.25em;
+ box-sizing: border-box;
+}
+
+
+img {
+ border: 0;
+ max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+ margin-top: 10px;
+}
+
+ul.search li {
+ padding: 5px 0;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li p.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+ width: 90%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.3em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+ font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+ width: 100%;
+}
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable ul {
+ margin-top: 0;
+ margin-bottom: 0;
+ list-style-type: none;
+}
+
+table.indextable > tbody > tr > td > ul {
+ padding-left: 0em;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+div.modindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+ border-top: 1px solid #ddd;
+ border-bottom: 1px solid #ddd;
+ margin: 1em 0 1em 0;
+ padding: 0.4em;
+}
+
+/* -- domain module index --------------------------------------------------- */
+
+table.modindextable td {
+ padding: 2px;
+ border-collapse: collapse;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+div.body {
+ min-width: 360px;
+ max-width: 800px;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+ -moz-hyphens: auto;
+ -ms-hyphens: auto;
+ -webkit-hyphens: auto;
+ hyphens: auto;
+}
+
+a.headerlink {
+ visibility: hidden;
+}
+
+a:visited {
+ color: #551A8B;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
+ visibility: visible;
+}
+
+div.body p.caption {
+ text-align: inherit;
+}
+
+div.body td {
+ text-align: left;
+}
+
+.first {
+ margin-top: 0 !important;
+}
+
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+img.align-left, figure.align-left, .figure.align-left, object.align-left {
+ clear: left;
+ float: left;
+ margin-right: 1em;
+}
+
+img.align-right, figure.align-right, .figure.align-right, object.align-right {
+ clear: right;
+ float: right;
+ margin-left: 1em;
+}
+
+img.align-center, figure.align-center, .figure.align-center, object.align-center {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+img.align-default, figure.align-default, .figure.align-default {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.align-left {
+ text-align: left;
+}
+
+.align-center {
+ text-align: center;
+}
+
+.align-default {
+ text-align: center;
+}
+
+.align-right {
+ text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar,
+aside.sidebar {
+ margin: 0 0 0.5em 1em;
+ border: 1px solid #ddb;
+ padding: 7px;
+ background-color: #ffe;
+ width: 40%;
+ float: right;
+ clear: right;
+ overflow-x: auto;
+}
+
+p.sidebar-title {
+ font-weight: bold;
+}
+
+nav.contents,
+aside.topic,
+div.admonition, div.topic, blockquote {
+ clear: left;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+nav.contents,
+aside.topic,
+div.topic {
+ border: 1px solid #ccc;
+ padding: 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+/* -- content of sidebars/topics/admonitions -------------------------------- */
+
+div.sidebar > :last-child,
+aside.sidebar > :last-child,
+nav.contents > :last-child,
+aside.topic > :last-child,
+div.topic > :last-child,
+div.admonition > :last-child {
+ margin-bottom: 0;
+}
+
+div.sidebar::after,
+aside.sidebar::after,
+nav.contents::after,
+aside.topic::after,
+div.topic::after,
+div.admonition::after,
+blockquote::after {
+ display: block;
+ content: '';
+ clear: both;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.align-center {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table.align-default {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table caption span.caption-number {
+ font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+ padding: 1px 8px 1px 5px;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+table.citation {
+ border-left: solid 1px gray;
+ margin-left: 1px;
+}
+
+table.citation td {
+ border-bottom: none;
+}
+
+th > :first-child,
+td > :first-child {
+ margin-top: 0px;
+}
+
+th > :last-child,
+td > :last-child {
+ margin-bottom: 0px;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure, figure {
+ margin: 0.5em;
+ padding: 0.5em;
+}
+
+div.figure p.caption, figcaption {
+ padding: 0.3em;
+}
+
+div.figure p.caption span.caption-number,
+figcaption span.caption-number {
+ font-style: italic;
+}
+
+div.figure p.caption span.caption-text,
+figcaption span.caption-text {
+}
+
+/* -- field list styles ----------------------------------------------------- */
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+.field-list ul {
+ margin: 0;
+ padding-left: 1em;
+}
+
+.field-list p {
+ margin: 0;
+}
+
+.field-name {
+ -moz-hyphens: manual;
+ -ms-hyphens: manual;
+ -webkit-hyphens: manual;
+ hyphens: manual;
+}
+
+/* -- hlist styles ---------------------------------------------------------- */
+
+table.hlist {
+ margin: 1em 0;
+}
+
+table.hlist td {
+ vertical-align: top;
+}
+
+/* -- object description styles --------------------------------------------- */
+
+.sig {
+ font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+}
+
+.sig-name, code.descname {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.sig-name {
+ font-size: 1.1em;
+}
+
+code.descname {
+ font-size: 1.2em;
+}
+
+.sig-prename, code.descclassname {
+ background-color: transparent;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.sig-paren {
+ font-size: larger;
+}
+
+.sig-param.n {
+ font-style: italic;
+}
+
+/* C++ specific styling */
+
+.sig-inline.c-texpr,
+.sig-inline.cpp-texpr {
+ font-family: unset;
+}
+
+.sig.c .k, .sig.c .kt,
+.sig.cpp .k, .sig.cpp .kt {
+ color: #0033B3;
+}
+
+.sig.c .m,
+.sig.cpp .m {
+ color: #1750EB;
+}
+
+.sig.c .s, .sig.c .sc,
+.sig.cpp .s, .sig.cpp .sc {
+ color: #067D17;
+}
+
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+ list-style: decimal;
+}
+
+ol.loweralpha {
+ list-style: lower-alpha;
+}
+
+ol.upperalpha {
+ list-style: upper-alpha;
+}
+
+ol.lowerroman {
+ list-style: lower-roman;
+}
+
+ol.upperroman {
+ list-style: upper-roman;
+}
+
+:not(li) > ol > li:first-child > :first-child,
+:not(li) > ul > li:first-child > :first-child {
+ margin-top: 0px;
+}
+
+:not(li) > ol > li:last-child > :last-child,
+:not(li) > ul > li:last-child > :last-child {
+ margin-bottom: 0px;
+}
+
+ol.simple ol p,
+ol.simple ul p,
+ul.simple ol p,
+ul.simple ul p {
+ margin-top: 0;
+}
+
+ol.simple > li:not(:first-child) > p,
+ul.simple > li:not(:first-child) > p {
+ margin-top: 0;
+}
+
+ol.simple p,
+ul.simple p {
+ margin-bottom: 0;
+}
+
+aside.footnote > span,
+div.citation > span {
+ float: left;
+}
+aside.footnote > span:last-of-type,
+div.citation > span:last-of-type {
+ padding-right: 0.5em;
+}
+aside.footnote > p {
+ margin-left: 2em;
+}
+div.citation > p {
+ margin-left: 4em;
+}
+aside.footnote > p:last-of-type,
+div.citation > p:last-of-type {
+ margin-bottom: 0em;
+}
+aside.footnote > p:last-of-type:after,
+div.citation > p:last-of-type:after {
+ content: "";
+ clear: both;
+}
+
+dl.field-list {
+ display: grid;
+ grid-template-columns: fit-content(30%) auto;
+}
+
+dl.field-list > dt {
+ font-weight: bold;
+ word-break: break-word;
+ padding-left: 0.5em;
+ padding-right: 5px;
+}
+
+dl.field-list > dd {
+ padding-left: 0.5em;
+ margin-top: 0em;
+ margin-left: 0em;
+ margin-bottom: 0em;
+}
+
+dl {
+ margin-bottom: 15px;
+}
+
+dd > :first-child {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+.sig dd {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.sig dl {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+dl > dd:last-child,
+dl > dd:last-child > :last-child {
+ margin-bottom: 0;
+}
+
+dt:target, span.highlighted {
+ background-color: #fbe54e;
+}
+
+rect.highlighted {
+ fill: #fbe54e;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+.system-message {
+ background-color: #fda;
+ padding: 5px;
+ border: 3px solid red;
+}
+
+.footnote:target {
+ background-color: #ffa;
+}
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+ font-family: sans-serif;
+}
+
+.accelerator {
+ text-decoration: underline;
+}
+
+.classifier {
+ font-style: oblique;
+}
+
+.classifier:before {
+ font-style: normal;
+ margin: 0 0.5em;
+ content: ":";
+ display: inline-block;
+}
+
+abbr, acronym {
+ border-bottom: dotted 1px;
+ cursor: help;
+}
+
+.translated {
+ background-color: rgba(207, 255, 207, 0.2)
+}
+
+.untranslated {
+ background-color: rgba(255, 207, 207, 0.2)
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+ overflow: auto;
+ overflow-y: hidden; /* fixes display issues on Chrome browsers */
+}
+
+pre, div[class*="highlight-"] {
+ clear: both;
+}
+
+span.pre {
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ -webkit-hyphens: none;
+ hyphens: none;
+ white-space: nowrap;
+}
+
+div[class*="highlight-"] {
+ margin: 1em 0;
+}
+
+td.linenos pre {
+ border: 0;
+ background-color: transparent;
+ color: #aaa;
+}
+
+table.highlighttable {
+ display: block;
+}
+
+table.highlighttable tbody {
+ display: block;
+}
+
+table.highlighttable tr {
+ display: flex;
+}
+
+table.highlighttable td {
+ margin: 0;
+ padding: 0;
+}
+
+table.highlighttable td.linenos {
+ padding-right: 0.5em;
+}
+
+table.highlighttable td.code {
+ flex: 1;
+ overflow: hidden;
+}
+
+.highlight .hll {
+ display: block;
+}
+
+div.highlight pre,
+table.highlighttable pre {
+ margin: 0;
+}
+
+div.code-block-caption + div {
+ margin-top: 0;
+}
+
+div.code-block-caption {
+ margin-top: 1em;
+ padding: 2px 5px;
+ font-size: small;
+}
+
+div.code-block-caption code {
+ background-color: transparent;
+}
+
+table.highlighttable td.linenos,
+span.linenos,
+div.highlight span.gp { /* gp: Generic.Prompt */
+ user-select: none;
+ -webkit-user-select: text; /* Safari fallback only */
+ -webkit-user-select: none; /* Chrome/Safari */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* IE10+ */
+}
+
+div.code-block-caption span.caption-number {
+ padding: 0.1em 0.3em;
+ font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+ margin: 1em 0;
+}
+
+code.xref, a code {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+ background-color: transparent;
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+ margin: -1px -10px;
+ padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+ vertical-align: middle;
+}
+
+div.body div.math p {
+ text-align: center;
+}
+
+span.eqno {
+ float: right;
+}
+
+span.eqno a.headerlink {
+ position: absolute;
+ z-index: 1;
+}
+
+div.math:hover a.headerlink {
+ visibility: visible;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+ div.document,
+ div.documentwrapper,
+ div.bodywrapper {
+ margin: 0 !important;
+ width: 100%;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ #top-link {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/docs/build/html/_static/css/badge_only.css b/docs/build/html/_static/css/badge_only.css
new file mode 100644
index 00000000..88ba55b9
--- /dev/null
+++ b/docs/build/html/_static/css/badge_only.css
@@ -0,0 +1 @@
+.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}
\ No newline at end of file
diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff
new file mode 100644
index 00000000..6cb60000
Binary files /dev/null and b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff differ
diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2
new file mode 100644
index 00000000..7059e231
Binary files /dev/null and b/docs/build/html/_static/css/fonts/Roboto-Slab-Bold.woff2 differ
diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff
new file mode 100644
index 00000000..f815f63f
Binary files /dev/null and b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff differ
diff --git a/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2
new file mode 100644
index 00000000..f2c76e5b
Binary files /dev/null and b/docs/build/html/_static/css/fonts/Roboto-Slab-Regular.woff2 differ
diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.eot b/docs/build/html/_static/css/fonts/fontawesome-webfont.eot
new file mode 100644
index 00000000..e9f60ca9
Binary files /dev/null and b/docs/build/html/_static/css/fonts/fontawesome-webfont.eot differ
diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.svg b/docs/build/html/_static/css/fonts/fontawesome-webfont.svg
new file mode 100644
index 00000000..855c845e
--- /dev/null
+++ b/docs/build/html/_static/css/fonts/fontawesome-webfont.svg
@@ -0,0 +1,2671 @@
+
+
+
diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf b/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf
new file mode 100644
index 00000000..35acda2f
Binary files /dev/null and b/docs/build/html/_static/css/fonts/fontawesome-webfont.ttf differ
diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.woff b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff
new file mode 100644
index 00000000..400014a4
Binary files /dev/null and b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff differ
diff --git a/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2
new file mode 100644
index 00000000..4d13fc60
Binary files /dev/null and b/docs/build/html/_static/css/fonts/fontawesome-webfont.woff2 differ
diff --git a/docs/build/html/_static/css/fonts/lato-bold-italic.woff b/docs/build/html/_static/css/fonts/lato-bold-italic.woff
new file mode 100644
index 00000000..88ad05b9
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-bold-italic.woff differ
diff --git a/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 b/docs/build/html/_static/css/fonts/lato-bold-italic.woff2
new file mode 100644
index 00000000..c4e3d804
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-bold-italic.woff2 differ
diff --git a/docs/build/html/_static/css/fonts/lato-bold.woff b/docs/build/html/_static/css/fonts/lato-bold.woff
new file mode 100644
index 00000000..c6dff51f
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-bold.woff differ
diff --git a/docs/build/html/_static/css/fonts/lato-bold.woff2 b/docs/build/html/_static/css/fonts/lato-bold.woff2
new file mode 100644
index 00000000..bb195043
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-bold.woff2 differ
diff --git a/docs/build/html/_static/css/fonts/lato-normal-italic.woff b/docs/build/html/_static/css/fonts/lato-normal-italic.woff
new file mode 100644
index 00000000..76114bc0
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-normal-italic.woff differ
diff --git a/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 b/docs/build/html/_static/css/fonts/lato-normal-italic.woff2
new file mode 100644
index 00000000..3404f37e
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-normal-italic.woff2 differ
diff --git a/docs/build/html/_static/css/fonts/lato-normal.woff b/docs/build/html/_static/css/fonts/lato-normal.woff
new file mode 100644
index 00000000..ae1307ff
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-normal.woff differ
diff --git a/docs/build/html/_static/css/fonts/lato-normal.woff2 b/docs/build/html/_static/css/fonts/lato-normal.woff2
new file mode 100644
index 00000000..3bf98433
Binary files /dev/null and b/docs/build/html/_static/css/fonts/lato-normal.woff2 differ
diff --git a/docs/build/html/_static/css/theme.css b/docs/build/html/_static/css/theme.css
new file mode 100644
index 00000000..0f14f106
--- /dev/null
+++ b/docs/build/html/_static/css/theme.css
@@ -0,0 +1,4 @@
+html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*!
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search .wy-dropdown>aactive,.wy-side-nav-search .wy-dropdown>afocus,.wy-side-nav-search>a:hover,.wy-side-nav-search>aactive,.wy-side-nav-search>afocus{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon,.wy-side-nav-search>a.icon{display:block}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.switch-menus{position:relative;display:block;margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-side-nav-search>div.switch-menus>div.language-switch,.wy-side-nav-search>div.switch-menus>div.version-switch{display:inline-block;padding:.2em}.wy-side-nav-search>div.switch-menus>div.language-switch select,.wy-side-nav-search>div.switch-menus>div.version-switch select{display:inline-block;margin-right:-2rem;padding-right:2rem;max-width:240px;text-align-last:center;background:none;border:none;border-radius:0;box-shadow:none;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-size:1em;font-weight:400;color:hsla(0,0%,100%,.3);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none}.wy-side-nav-search>div.switch-menus>div.language-switch select:active,.wy-side-nav-search>div.switch-menus>div.language-switch select:focus,.wy-side-nav-search>div.switch-menus>div.language-switch select:hover,.wy-side-nav-search>div.switch-menus>div.version-switch select:active,.wy-side-nav-search>div.switch-menus>div.version-switch select:focus,.wy-side-nav-search>div.switch-menus>div.version-switch select:hover{background:hsla(0,0%,100%,.1);color:hsla(0,0%,100%,.5)}.wy-side-nav-search>div.switch-menus>div.language-switch select option,.wy-side-nav-search>div.switch-menus>div.version-switch select option{color:#000}.wy-side-nav-search>div.switch-menus>div.language-switch:has(>select):after,.wy-side-nav-search>div.switch-menus>div.version-switch:has(>select):after{display:inline-block;width:1.5em;height:100%;padding:.1em;content:"\f0d7";font-size:1em;line-height:1.2em;font-family:FontAwesome;text-align:center;pointer-events:none;box-sizing:border-box}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions .rst-other-versions .rtd-current-item{font-weight:700}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}#flyout-search-form{padding:6px}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block}
\ No newline at end of file
diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js
new file mode 100644
index 00000000..0398ebb9
--- /dev/null
+++ b/docs/build/html/_static/doctools.js
@@ -0,0 +1,149 @@
+/*
+ * Base JavaScript utilities for all Sphinx HTML documentation.
+ */
+"use strict";
+
+const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
+ "TEXTAREA",
+ "INPUT",
+ "SELECT",
+ "BUTTON",
+]);
+
+const _ready = (callback) => {
+ if (document.readyState !== "loading") {
+ callback();
+ } else {
+ document.addEventListener("DOMContentLoaded", callback);
+ }
+};
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+const Documentation = {
+ init: () => {
+ Documentation.initDomainIndexTable();
+ Documentation.initOnKeyListeners();
+ },
+
+ /**
+ * i18n support
+ */
+ TRANSLATIONS: {},
+ PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
+ LOCALE: "unknown",
+
+ // gettext and ngettext don't access this so that the functions
+ // can safely bound to a different name (_ = Documentation.gettext)
+ gettext: (string) => {
+ const translated = Documentation.TRANSLATIONS[string];
+ switch (typeof translated) {
+ case "undefined":
+ return string; // no translation
+ case "string":
+ return translated; // translation exists
+ default:
+ return translated[0]; // (singular, plural) translation tuple exists
+ }
+ },
+
+ ngettext: (singular, plural, n) => {
+ const translated = Documentation.TRANSLATIONS[singular];
+ if (typeof translated !== "undefined")
+ return translated[Documentation.PLURAL_EXPR(n)];
+ return n === 1 ? singular : plural;
+ },
+
+ addTranslations: (catalog) => {
+ Object.assign(Documentation.TRANSLATIONS, catalog.messages);
+ Documentation.PLURAL_EXPR = new Function(
+ "n",
+ `return (${catalog.plural_expr})`
+ );
+ Documentation.LOCALE = catalog.locale;
+ },
+
+ /**
+ * helper function to focus on search bar
+ */
+ focusSearchBar: () => {
+ document.querySelectorAll("input[name=q]")[0]?.focus();
+ },
+
+ /**
+ * Initialise the domain index toggle buttons
+ */
+ initDomainIndexTable: () => {
+ const toggler = (el) => {
+ const idNumber = el.id.substr(7);
+ const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
+ if (el.src.substr(-9) === "minus.png") {
+ el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
+ toggledRows.forEach((el) => (el.style.display = "none"));
+ } else {
+ el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
+ toggledRows.forEach((el) => (el.style.display = ""));
+ }
+ };
+
+ const togglerElements = document.querySelectorAll("img.toggler");
+ togglerElements.forEach((el) =>
+ el.addEventListener("click", (event) => toggler(event.currentTarget))
+ );
+ togglerElements.forEach((el) => (el.style.display = ""));
+ if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
+ },
+
+ initOnKeyListeners: () => {
+ // only install a listener if it is really needed
+ if (
+ !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
+ !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
+ )
+ return;
+
+ document.addEventListener("keydown", (event) => {
+ // bail for input elements
+ if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
+ // bail with special keys
+ if (event.altKey || event.ctrlKey || event.metaKey) return;
+
+ if (!event.shiftKey) {
+ switch (event.key) {
+ case "ArrowLeft":
+ if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+ const prevLink = document.querySelector('link[rel="prev"]');
+ if (prevLink && prevLink.href) {
+ window.location.href = prevLink.href;
+ event.preventDefault();
+ }
+ break;
+ case "ArrowRight":
+ if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
+
+ const nextLink = document.querySelector('link[rel="next"]');
+ if (nextLink && nextLink.href) {
+ window.location.href = nextLink.href;
+ event.preventDefault();
+ }
+ break;
+ }
+ }
+
+ // some keyboard layouts may need Shift to get /
+ switch (event.key) {
+ case "/":
+ if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
+ Documentation.focusSearchBar();
+ event.preventDefault();
+ }
+ });
+ },
+};
+
+// quick alias for translations
+const _ = Documentation.gettext;
+
+_ready(Documentation.init);
diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js
new file mode 100644
index 00000000..7e4c114f
--- /dev/null
+++ b/docs/build/html/_static/documentation_options.js
@@ -0,0 +1,13 @@
+const DOCUMENTATION_OPTIONS = {
+ VERSION: '',
+ LANGUAGE: 'en',
+ COLLAPSE_INDEX: false,
+ BUILDER: 'html',
+ FILE_SUFFIX: '.html',
+ LINK_SUFFIX: '.html',
+ HAS_SOURCE: true,
+ SOURCELINK_SUFFIX: '.txt',
+ NAVIGATION_WITH_KEYS: false,
+ SHOW_SEARCH_SUMMARY: true,
+ ENABLE_SEARCH_SHORTCUTS: true,
+};
\ No newline at end of file
diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png
new file mode 100644
index 00000000..a858a410
Binary files /dev/null and b/docs/build/html/_static/file.png differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.eot b/docs/build/html/_static/fonts/Lato/lato-bold.eot
new file mode 100644
index 00000000..3361183a
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bold.eot differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.ttf b/docs/build/html/_static/fonts/Lato/lato-bold.ttf
new file mode 100644
index 00000000..29f691d5
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bold.ttf differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.woff b/docs/build/html/_static/fonts/Lato/lato-bold.woff
new file mode 100644
index 00000000..c6dff51f
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bold.woff differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bold.woff2 b/docs/build/html/_static/fonts/Lato/lato-bold.woff2
new file mode 100644
index 00000000..bb195043
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bold.woff2 differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot b/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot
new file mode 100644
index 00000000..3d415493
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bolditalic.eot differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf b/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf
new file mode 100644
index 00000000..f402040b
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bolditalic.ttf differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff b/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff
new file mode 100644
index 00000000..88ad05b9
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 b/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2
new file mode 100644
index 00000000..c4e3d804
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-bolditalic.woff2 differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.eot b/docs/build/html/_static/fonts/Lato/lato-italic.eot
new file mode 100644
index 00000000..3f826421
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-italic.eot differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.ttf b/docs/build/html/_static/fonts/Lato/lato-italic.ttf
new file mode 100644
index 00000000..b4bfc9b2
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-italic.ttf differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.woff b/docs/build/html/_static/fonts/Lato/lato-italic.woff
new file mode 100644
index 00000000..76114bc0
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-italic.woff differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-italic.woff2 b/docs/build/html/_static/fonts/Lato/lato-italic.woff2
new file mode 100644
index 00000000..3404f37e
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-italic.woff2 differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.eot b/docs/build/html/_static/fonts/Lato/lato-regular.eot
new file mode 100644
index 00000000..11e3f2a5
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-regular.eot differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.ttf b/docs/build/html/_static/fonts/Lato/lato-regular.ttf
new file mode 100644
index 00000000..74decd9e
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-regular.ttf differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.woff b/docs/build/html/_static/fonts/Lato/lato-regular.woff
new file mode 100644
index 00000000..ae1307ff
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-regular.woff differ
diff --git a/docs/build/html/_static/fonts/Lato/lato-regular.woff2 b/docs/build/html/_static/fonts/Lato/lato-regular.woff2
new file mode 100644
index 00000000..3bf98433
Binary files /dev/null and b/docs/build/html/_static/fonts/Lato/lato-regular.woff2 differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot
new file mode 100644
index 00000000..79dc8efe
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
new file mode 100644
index 00000000..df5d1df2
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff
new file mode 100644
index 00000000..6cb60000
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2
new file mode 100644
index 00000000..7059e231
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot
new file mode 100644
index 00000000..2f7ca78a
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
new file mode 100644
index 00000000..eb52a790
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff
new file mode 100644
index 00000000..f815f63f
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff differ
diff --git a/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2
new file mode 100644
index 00000000..f2c76e5b
Binary files /dev/null and b/docs/build/html/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 differ
diff --git a/docs/build/html/_static/jquery.js b/docs/build/html/_static/jquery.js
new file mode 100644
index 00000000..c4c6022f
--- /dev/null
+++ b/docs/build/html/_static/jquery.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"
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 open_resource().
+
Usually you create a Flask instance in your main module or
+in the __init__.py file of your package like this:
+
fromflaskimportFlask
+app=Flask(__name__)
+
+
+
+
About the First Parameter
+
The idea of the first parameter is to give Flask an idea of what
+belongs to your application. This name is used to find resources
+on the filesystem, 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:
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 yourapplication.app and not
+yourapplication.views.frontend)
+
+
+
Added in version 0.7: The static_url_path, static_folder, and template_folder
+parameters were added.
+
+
+
Added in version 0.8: The instance_path and instance_relative_config parameters were
+added.
+
+
+
Added in version 0.11: The root_path parameter was added.
+
+
+
Added in version 1.0: The host_matching and static_host parameters were added.
+
+
+
Added in version 1.0: The subdomain_matching parameter was added. Subdomain
+matching needs to be enabled manually now. Setting
+SERVER_NAME does not implicitly enable it.
+
+
+
Parameters:
+
+
import_name – the name of the application package
+
static_url_path – can be used to specify a different path for the
+static files on the web. Defaults to the name
+of the static_folder folder.
+
static_folder – The folder with static files that is served at
+static_url_path. Relative to the application root_path
+or an absolute path. Defaults to 'static'.
+
static_host – the host to use when adding the static route.
+Defaults to None. Required when using host_matching=True
+with a static_folder configured.
+
host_matching – set url_map.host_matching attribute.
+Defaults to False.
+
subdomain_matching – consider the subdomain relative to
+SERVER_NAME when matching routes. Defaults to False.
+
template_folder – the folder that contains the templates that should
+be used by the application. Defaults to
+'templates' folder in the root path of the
+application.
+
instance_path – An alternative instance path for the application.
+By default the folder 'instance' next to the
+package or module is assumed to be the instance
+path.
+
instance_relative_config – if set to True relative filenames
+for loading the config are assumed to
+be relative to the instance path instead
+of the application root.
+
root_path – The path to the root of the application files.
+This should only be set manually when it can’t be detected
+automatically, such as for namespace packages.
Create an AppContext. Use as a with
+block to push the context, which will make current_app
+point at this application.
+
An application context is automatically pushed by
+RequestContext.push()
+when handling a request, and when running a CLI command. Use
+this to manually create a context outside of these situations.
The Click command group for registering CLI commands for this
+object. The commands are available from the flask command
+once the application has been discovered and blueprints have
+been registered.
Create the Jinja environment based on jinja_options
+and the various Jinja-related methods of the app. Changing
+jinja_options after this will have no effect. Also adds
+Flask-related globals and filters to the environment.
+
+
Changed in version 0.11: Environment.auto_reload set in accordance with
+TEMPLATES_AUTO_RELOAD configuration option.
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.
+
+
Changed in version 3.1: If SERVER_NAME is set, it does not restrict requests to
+only that domain, for both subdomain_matching and
+host_matching.
+
+
+
Changed in version 1.0: SERVER_NAME no longer implicitly enables subdomain
+matching. Use subdomain_matching instead.
+
+
+
Changed in version 0.9: This can be called outside a request when the URL adapter is created
+for an application context.
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 make_response().
+
+
Changed in version 0.7: This no longer does the exception handling, this code was
+moved to the new full_dispatch_request().
Called after the request is dispatched and the response is
+returned, right before the request context is popped.
+
This calls all functions decorated with
+teardown_request(), and Blueprint.teardown_request()
+if a blueprint handled the request. Finally, the
+request_tearing_down signal is sent.
+
This is called by
+RequestContext.pop(),
+which may be delayed during testing to maintain access to
+resources.
+
+
Parameters:
+
exc – An unhandled exception raised while dispatching the
+request. Detected from the current exception information if
+not passed. Passed to each teardown function.
Ensure that the function is synchronous for WSGI workers.
+Plain def functions are returned as-is. asyncdef
+functions are wrapped to run and wait for the response.
+
Override this method to change how the app runs async views.
Given the return value from a view function this finalizes
+the request by converting it into a response and invoking the
+postprocessing functions. This is invoked for both normal
+request dispatching as well as error handlers.
+
Because this means that it might be called as a result of a
+failure a special safe mode is available which can be enabled
+with the from_error_handler flag. If enabled, failures in
+response processing will be logged and otherwise ignored.
Used by send_file() to determine the max_age cache
+value for a given file path if it wasn’t passed.
+
By default, this returns SEND_FILE_MAX_AGE_DEFAULT from
+the configuration of current_app. This defaults
+to None, which tells the browser to use conditional requests
+instead of a timed cache, which is usually preferable.
+
Note this is a duplicate of the same method in the Flask
+class.
+
+
Changed in version 2.0: The default configuration is None instead of 12 hours.
Handle an exception that did not have an error handler
+associated with it, or that was raised from an error handler.
+This always causes a 500 InternalServerError.
+
Always sends the got_request_exception signal.
+
If PROPAGATE_EXCEPTIONS is True, such as in debug
+mode, the error will be re-raised so that the debugger can
+display it. Otherwise, the original exception is logged, and
+an InternalServerError is returned.
+
If an error handler is registered for InternalServerError or
+500, it will be used. For consistency, the handler will
+always receive the InternalServerError. The original
+unhandled exception is available as e.original_exception.
+
+
Changed in version 1.1.0: Always passes the InternalServerError instance to the
+handler, setting original_exception to the unhandled
+error.
+
+
+
Changed in version 1.1.0: after_request functions and other finalization is done
+even for the default 500 response when there is no handler.
Handles an HTTP exception. By default this will invoke the
+registered error handlers and fall back to returning the
+exception as response.
+
+
Changed in version 1.0.3: RoutingException, used internally for actions such as
+ slash redirects during routing, is not passed to error
+ handlers.
+
+
+
Changed in version 1.0: Exceptions are looked up by code and by MRO, so
+HTTPException subclasses can be handled with a catch-all
+handler for the base HTTPException.
This method is called whenever an exception occurs that
+should be handled. A special case is HTTPException which is forwarded to the
+handle_http_exception() method. This function will either
+return a response value or reraise the exception with the same
+traceback.
+
+
Changed in version 1.0: Key errors raised from request data like form show the
+bad key in debug mode rather than a generic bad request
+message.
Logs an exception. This is called by handle_exception()
+if debugging is disabled and right before the handler is called.
+The default implementation logs the exception as error on the
+logger.
This method is called to create the default OPTIONS response.
+This can be changed through subclassing to change the default
+behavior of OPTIONS responses.
Convert the return value from a view function to an instance of
+response_class.
+
+
Parameters:
+
rv –
the return value from the view function. The view function
+must return a response. Returning None, or the view ending
+without returning, is not allowed. The following types are allowed
+for view_rv:
+
+
str
A response object is created with the string encoded to UTF-8
+as the body.
+
+
bytes
A response object is created with the bytes as the body.
+
+
dict
A dictionary that will be jsonify’d before being returned.
+
+
list
A list that will be jsonify’d before being returned.
+
+
generator or iterator
A generator that returns str or bytes to be
+streamed as the response.
+
+
tuple
Either (body,status,headers), (body,status), or
+(body,headers), where body is any of the other types
+allowed here, status is a string or an integer, and
+headers is a dictionary or a list of (key,value)
+tuples. If body is a response_class instance,
+status overwrites the exiting value and headers are
+extended.
Open a resource file relative to the application’s instance folder
+instance_path. Unlike open_resource(), files in the
+instance folder can be opened for writing.
+
+
Parameters:
+
+
resource – Path to the resource relative to instance_path.
+
mode – Open the file in this mode.
+
encoding – Open the file with this encoding when opening in text
+mode. This is ignored when opening in binary mode.
+
+
+
+
+
Changed in version 3.1: Added the encoding parameter.
Called before the request is dispatched. Calls
+url_value_preprocessors registered with the app and the
+current blueprint (if any). Then calls before_request_funcs
+registered with the app and the blueprint.
+
If any before_request() handler returns a non-None value, the
+value is handled as if it was the return value from the view, and
+further request handling is stopped.
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 after_request() decorated functions.
+
+
Changed in version 0.5: As of Flask 0.5 the functions registered for after request
+execution are called in reverse order of registration.
Create a RequestContext representing a
+WSGI environment. Use a with block to push the context,
+which will make request point at this request.
+
See /reqcontext.
+
Typically you should not call this from your own code. A request
+context is automatically pushed by the wsgi_app() when
+handling a request. Use test_request_context() to create
+an environment and context instead of this method.
Runs the application on a local development server.
+
Do not use run() in a production setting. It is not intended to
+meet security and performance requirements for a production server.
+Instead, see /deploying/index for WSGI server recommendations.
+
If the 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.
+
It is not recommended to use this function for development with
+automatic reloading as this is badly supported. Instead you should
+be using the flask command line script’s run support.
+
+
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 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.
+
+
+
Parameters:
+
+
host – the hostname to listen on. Set this to '0.0.0.0' to
+have the server available externally as well. Defaults to
+'127.0.0.1' or the host in the SERVER_NAME config variable
+if present.
+
port – the port of the webserver. Defaults to 5000 or the
+port defined in the SERVER_NAME config variable if present.
+
debug – if given, enable or disable debug mode. See
+debug.
+
load_dotenv – Load the nearest .env and .flaskenv
+files to set environment variables. Will also change the working
+directory to the directory containing the first file found.
+
options – the options to be forwarded to the underlying Werkzeug
+server. See werkzeug.serving.run_simple() for more
+information.
+
+
+
+
+
Changed in version 1.0: If installed, python-dotenv will be used to load environment
+variables from .env and .flaskenv files.
+
The FLASK_DEBUG environment variable will override debug.
+
Threaded mode is enabled by default.
+
+
+
Changed in version 0.10: The default port is now picked from the SERVER_NAME
+variable.
The view function used to serve files from
+static_folder. A route is automatically registered for
+this view at static_url_path if static_folder is
+set.
+
Note this is a duplicate of the same method in the Flask
+class.
Creates a test client for this application. For information
+about unit testing head over to /testing.
+
Note that if you are testing for assertions or exceptions in your
+application code, you must set app.testing=True in order for the
+exceptions to propagate to the test client. Otherwise, the exception
+will be handled by the application (not visible to the test client) and
+the only indication of an AssertionError or other exception will be a
+500 status code response to the test client. See the testing
+attribute. For example:
+
app.testing=True
+client=app.test_client()
+
+
+
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:
Changed in version 0.4: added support for with block usage for the client.
+
+
+
Added in version 0.7: The use_cookies parameter was added as well as the ability
+to override the client to be used by setting the
+test_client_class attribute.
+
+
+
Changed in version 0.11: Added **kwargs to support passing additional keyword arguments to
+the constructor of test_client_class.
Create a RequestContext for a WSGI
+environment created from the given values. This is mostly useful
+during testing, where you may want to run a function that uses
+request data without dispatching a full request.
+
See /reqcontext.
+
Use a with block to push the context, which will make
+request point at the request for the created
+environment.
Takes the same arguments as Werkzeug’s
+EnvironBuilder, with some defaults from
+the application. See the linked Werkzeug docs for most of the
+available arguments. Flask-specific behavior is listed here.
+
+
Parameters:
+
+
path – URL path being requested.
+
base_url – Base URL where the app is being served, which
+path is relative to. If not given, built from
+PREFERRED_URL_SCHEME, subdomain,
+SERVER_NAME, and APPLICATION_ROOT.
+
subdomain – Subdomain name to append to
+SERVER_NAME.
+
url_scheme – Scheme to use instead of
+PREFERRED_URL_SCHEME.
+
data – The request body, either as a string or a dict of
+form keys and values.
+
json – If given, this is serialized as JSON and passed as
+data. Also defaults content_type to
+application/json.
+
args – other positional arguments passed to
+EnvironBuilder.
+
kwargs – other keyword arguments passed to
+EnvironBuilder.
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 overridden if a context processor
+decides to return a value with the same key.
+
+
Parameters:
+
context – the context as a dictionary that is updated in place
+to add extra variables.
Generate a URL to the given endpoint with the given values.
+
This is called by flask.url_for(), and can be called
+directly as well.
+
An endpoint is the name of a URL rule, usually added with
+@app.route(), and usually the same name as the
+view function. A route defined in a Blueprint
+will prepend the blueprint’s name separated by a . to the
+endpoint.
+
In some cases, such as email messages, you want URLs to include
+the scheme and domain, like https://example.com/hello. When
+not in an active request, URLs will be external by default, but
+this requires setting SERVER_NAME so Flask knows what
+domain to use. APPLICATION_ROOT and
+PREFERRED_URL_SCHEME should also be configured as
+needed. This config is only used when not in an active request.
+
Functions can be decorated with url_defaults() to modify
+keyword arguments before the URL is built.
+
If building fails for some reason, such as an unknown endpoint
+or incorrect values, the app’s handle_url_build_error()
+method is called. If that returns a string, that is returned,
+otherwise a BuildError is raised.
+
+
Parameters:
+
+
endpoint – The endpoint name associated with the URL to
+generate. If this starts with a ., the current blueprint
+name (if any) will be used.
+
_anchor – If given, append this as #anchor to the URL.
+
_method – If given, generate the URL associated with this
+method for the endpoint.
+
_scheme – If given, the URL will have this scheme if it
+is external.
+
_external – If given, prefer the URL to be internal
+(False) or require it to be external (True). External URLs
+include the scheme and domain. When not in an active
+request, URLs are external by default.
+
values – Values to use for the variable parts of the URL
+rule. Unknown keys are appended as query string arguments,
+like ?a=b&c=d.
+
+
+
+
+
Added in version 2.2: Moved from flask.url_for, which calls this method.
The actual WSGI application. This is not implemented in
+__call__() so that middlewares can be applied without
+losing a reference to the app object. 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.
+
+
Changed in version 0.7: Teardown events for the request and app contexts are called
+even if an unhandled error occurs. Other events may not be
+called depending on when an error occurs during dispatch.
+See callbacks-and-errors.
+
+
+
Parameters:
+
+
environ – A WSGI environment.
+
start_response – A callable accepting a status code,
+a list of headers, and an optional exception context to
+start the response.
The Click command group for registering CLI commands for this
+object. The commands are available from the flask command
+once the application has been discovered and blueprints have
+been registered.
Used by send_file() to determine the max_age cache
+value for a given file path if it wasn’t passed.
+
By default, this returns SEND_FILE_MAX_AGE_DEFAULT from
+the configuration of current_app. This defaults
+to None, which tells the browser to use conditional requests
+instead of a timed cache, which is usually preferable.
+
Note this is a duplicate of the same method in the Flask
+class.
+
+
Changed in version 2.0: The default configuration is None instead of 12 hours.
The view function used to serve files from
+static_folder. A route is automatically registered for
+this view at static_url_path if static_folder is
+set.
+
Note this is a duplicate of the same method in the Flask
+class.
This works similar to a regular click Group but it
+changes the behavior of the command() decorator so that it
+automatically wraps the functions in with_appcontext().
This works exactly like the method of the same name on a regular
+click.Group but it wraps callbacks in with_appcontext()
+unless it’s disabled by passing with_appcontext=False.
Convert the value to the correct type. This is not called if
+the value is None (the missing value).
+
This must accept string values from the command line, as well as
+values that are already the correct type. It may also convert
+other compatible types.
+
The param and ctx arguments may be None in certain
+situations, such as when converting prompt input.
+
If the value cannot be converted, call fail() with a
+descriptive message.
+
+
Parameters:
+
+
value – The value to convert.
+
param – The parameter that is using this type to convert
+its value. May be None.
+
ctx – The current context that arrived at this value. May
+be None.
Special subclass of the AppGroup group that supports
+loading more commands from the configured Flask app. Normally a
+developer does not have to interface with this class but there are
+some very advanced use cases for which it makes sense to create an
+instance of this. see custom-scripts.
+
+
Parameters:
+
+
add_default_commands – if this is True then the default run and
+shell commands will be added.
+
add_version_option – adds the --version option.
+
create_app – an optional callback that is passed the script info and
+returns the loaded app.
+
load_dotenv – Load the nearest .env and .flaskenv
+files to set environment variables. Will also change the working
+directory to the directory containing the first file found.
+
set_debug_flag – Set the app’s debug flag.
+
+
+
+
+
Changed in version 3.1: -epath takes precedence over default .env and .flaskenv files.
+
+
+
Changed in version 2.2: Added the -A/--app, --debug/--no-debug, -e/--env-file options.
+
+
+
Changed in version 2.2: An app context is pushed when running app.cli commands, so
+@with_appcontext is no longer required for those commands.
+
+
+
Changed in version 1.0: If installed, python-dotenv will be used to load environment variables
+from .env and .flaskenv files.
This function when given an info name and arguments will kick
+off the parsing and create a new Context. It does not
+invoke the actual command callback though.
+
To quickly customize the context class used without overriding
+this method, set the context_class attribute.
+
+
Parameters:
+
+
info_name – the info name for this invocation. Generally this
+is the most descriptive name for the script or
+command. For the toplevel script it’s usually
+the name of the script, for commands below it’s
+the name of the command.
+
args – the arguments to parse as list of strings.
+
parent – the parent context if available.
+
extra – extra keyword arguments forwarded to the context
+constructor.
+
+
+
+
+
Changed in version 8.0: Added the context_class attribute.
Given a context and a list of arguments this creates the parser
+and parses the arguments, then modifies the context as necessary.
+This is automatically invoked by make_context().
Helper object to deal with Flask applications. This is usually not
+necessary to interface with as it’s used internally in the dispatching
+to click. In future versions of Flask this object will most likely play
+a bigger role. Typically it’s created automatically by the
+FlaskGroup but you can also manually create it and pass it
+onwards as click object.
+
+
Changed in version 3.1: Added the load_dotenv_defaults parameter and attribute.
Click option type that accepts a list of values separated by the
+OS’s path separator (:, ; on Windows). Each value is
+validated as a click.Path type.
Convert the value to the correct type. This is not called if
+the value is None (the missing value).
+
This must accept string values from the command line, as well as
+values that are already the correct type. It may also convert
+other compatible types.
+
The param and ctx arguments may be None in certain
+situations, such as when converting prompt input.
+
If the value cannot be converted, call fail() with a
+descriptive message.
+
+
Parameters:
+
+
value – The value to convert.
+
param – The parameter that is using this type to convert
+its value. May be None.
+
ctx – The current context that arrived at this value. May
+be None.
Load “dotenv” files to set environment variables. A given path takes
+precedence over .env, which takes precedence over .flaskenv. After
+loading and combining these files, values are only set if the key is not
+already set in os.environ.
Wraps a callback so that it’s guaranteed to be executed with the
+script’s application context.
+
Custom commands (and their options) registered under app.cli or
+blueprint.cli will always have an app context available, this
+decorator is not required in that case.
+
+
Changed in version 2.2: The app context is active for subcommands as well as the
+decorated callback. The app context is always available to
+app.cli command and parameter callbacks.
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 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:
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:
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:
Loads a configuration from an environment variable pointing to
+a configuration file. This is basically just a shortcut with nicer
+error messages for this line of code:
filename – The path to the data file. This can be an
+absolute path or relative to the config root path.
+
load (Callable[[Reader],Mapping] where Reader
+implements a read method.) – A callable that takes a file handle and returns a
+mapping of loaded data from the file.
+
silent – Ignore the file if it doesn’t exist.
+
text – Open the file in text or binary mode.
+
+
+
Returns:
+
True if the file was loaded successfully.
+
+
+
+
Changed in version 2.3: The text parameter was added.
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. from_object()
+loads only the uppercase attributes of the module/class. A dict
+object will not work with from_object() because the keys of a
+dict are not attributes of the dict class.
Nothing is done to the object before loading. If the object is a
+class and has @property attributes, it needs to be
+instantiated before being passed to this method.
+
You should not use this function to load the actual configuration but
+rather configuration defaults. The actual config should be loaded
+with from_pyfile() and ideally from a location not within the
+package because the package might be installed system wide.
+
See config-dev-prod for an example of class-based configuration
+using from_object().
Load any environment variables that start with FLASK_,
+dropping the prefix from the env key for the config key. Values
+are passed through a loading function to attempt to convert them
+to more specific types than strings.
+
Keys are loaded in sorted() order.
+
The default loading function attempts to parse values as any
+valid JSON type, including dicts and lists.
+
Specific items in nested dicts can be set by separating the
+keys with double underscores (__). If an intermediate key
+doesn’t exist, it will be initialized to an empty dict.
+
+
Parameters:
+
+
prefix – Load env vars that start with this prefix,
+separated with an underscore (_).
+
loads – Pass each string value to this function and use
+the returned value as the config value. If any error is
+raised it is ignored and the value remains a string. The
+default is json.loads().
The app context contains application-specific information. An app
+context is created and pushed at the beginning of each request if
+one is not already active. An app context is also pushed when
+running CLI commands.
The request context contains per-request information. The Flask
+app creates and pushes it at the beginning of the request, then pops
+it at the end of the request. It will create the URL adapter and
+request object for the WSGI environment provided.
+
Do not attempt to use this class directly, instead use
+test_request_context() and
+request_context() to create this object.
+
When the request context is popped, it will evaluate all the
+functions registered on the application for teardown execution
+(teardown_request()).
+
The request context is automatically popped at the end of the
+request. When using the interactive debugger, the context will be
+restored so request is still accessible. Similarly, the test
+client can preserve the context after the request ends. However,
+teardown functions may already have closed some resources such as
+database connections.
Creates a copy of this request context with the same request object.
+This can be used to move a request context to a different greenlet.
+Because the actual request object is the same this cannot be used to
+move a request context to a different thread unless access to the
+request object is locked.
+
+
Added in version 0.10.
+
+
+
Changed in version 1.1: The current session object is used instead of reloading the original
+data. This prevents flask.session pointing to an out-of-date object.
Pops the request context and unbinds it by doing that. This will
+also trigger the execution of functions registered by the
+teardown_request() decorator.
Executes a function after this request. This is useful to modify
+response objects. The function is passed the response object and has
+to return the same or a new one.
This is more useful if a function other than the view function wants to
+modify a response. For instance think of a decorator that wants to add
+some headers without converting the return value into a response object.
A helper function that decorates a function to retain the current
+request context. This is useful when working with greenlets. The moment
+the function is decorated a copy of the request context is created and
+then pushed when the function is called. The current session is also
+included in the copied request context.
+
Example:
+
importgevent
+fromflaskimportcopy_current_request_context
+
+@app.route('/')
+defindex():
+ @copy_current_request_context
+ defdo_some_work():
+ # do some work here, it can access flask.request or
+ # flask.session like you would otherwise in the view function.
+ ...
+ gevent.spawn(do_some_work)
+ return'Regular response'
+
If you have code that wants to test if a request context is there or
+not this function can be used. For instance, you may want to take advantage
+of request information if the request object is available, but fail
+silently if it is unavailable.
This exception is raised in debug mode if a routing redirect
+would cause the browser to drop the method or body. This happens
+when method is not GET, HEAD or OPTIONS and the status code is not
+307 or 308.
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 get_flashed_messages().
+
+
Changed in version 0.3: category parameter added.
+
+
+
Parameters:
+
+
message – the message to be flashed.
+
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.
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.
+
Filter the flashed messages to one or more categories by providing those
+categories in category_filter. This allows rendering categories in
+separate html blocks. The with_categories and category_filter
+arguments are distinct:
+
+
with_categories controls whether categories are returned with message
+text (True gives a tuple, where False gives just the message text).
+
category_filter filters the messages down to only those matching the
+provided categories.
+
+
See /patterns/flashing for examples.
+
+
Changed in version 0.3: with_categories parameter added.
+
+
+
Changed in version 0.9: category_filter parameter added.
+
+
+
Parameters:
+
+
with_categories – set to True to also receive categories.
+
category_filter – filter of categories to limit return values. Only
+categories in the list will be returned.
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:
Sometimes it is necessary to set additional headers in a view. Because
+views do not have to return response objects but can return a value that
+is converted into a response object by Flask itself, it becomes tricky to
+add headers to it. This function can be called instead of using a return
+and you will get a response object which you can use to attach headers.
+
If view looked like this and you want to add a new header:
The first argument can be a file path or a file-like object. Paths
+are preferred in most cases because Werkzeug can manage the file and
+get extra information from the path. Passing a file-like object
+requires that the file is opened in binary mode, and is mostly
+useful when building a file in memory with io.BytesIO.
+
Never pass file paths provided by a user. The path is assumed to be
+trusted, so a user could craft a path to access a file you didn’t
+intend. Use send_from_directory() to safely serve
+user-requested paths from within a directory.
+
If the WSGI server sets a file_wrapper in environ, it is
+used, otherwise Werkzeug’s built-in wrapper is used. Alternatively,
+if the HTTP server supports X-Sendfile, configuring Flask with
+USE_X_SENDFILE=True will tell the server to send the given
+path, which is much more efficient than reading it in Python.
+
+
Parameters:
+
+
path_or_file – The path to the file to send, relative to the
+current working directory if a relative path is given.
+Alternatively, a file-like object opened in binary mode. Make
+sure the file pointer is seeked to the start of the data.
+
mimetype – The MIME type to send for the file. If not
+provided, it will try to detect it from the file name.
+
as_attachment – Indicate to a browser that it should offer to
+save the file instead of displaying it.
+
download_name – The default name browsers will use when saving
+the file. Defaults to the passed file name.
+
conditional – Enable conditional and range responses based on
+request headers. Requires passing a file path and environ.
+
etag – Calculate an ETag for the file, which requires passing
+a file path. Can also be a string to use instead.
+
last_modified – The last modified time to send for the file,
+in seconds. If not provided, it will try to detect it from the
+file path.
+
max_age – How long the client should cache the file, in
+seconds. If set, Cache-Control will be public, otherwise
+it will be no-cache to prefer conditional caching.
+
+
+
+
+
Changed in version 2.0: download_name replaces the attachment_filename
+parameter. If as_attachment=False, it is passed with
+Content-Disposition:inline instead.
+
+
+
Changed in version 2.0: max_age replaces the cache_timeout parameter.
+conditional is enabled and max_age is not set by
+default.
+
+
+
Changed in version 2.0: etag replaces the add_etags parameter. It can be a
+string to use instead of generating one.
+
+
+
Changed in version 2.0: Passing a file-like object that inherits from
+TextIOBase will raise a ValueError rather
+than sending an empty file.
+
+
+
Added in version 2.0: Moved the implementation to Werkzeug. This is now a wrapper to
+pass some Flask-specific arguments.
+
+
+
Changed in version 1.1: filename may be a PathLike object.
+
+
+
Changed in version 1.1: Passing a BytesIO object supports range requests.
+
+
+
Changed in version 1.0.3: Filenames are encoded with ASCII instead of Latin-1 for broader
+compatibility with WSGI servers.
+
+
+
Changed in version 1.0: UTF-8 filenames as specified in RFC 2231 are supported.
+
+
+
Changed in version 0.12: The filename is no longer automatically inferred from file
+objects. If you want to use automatic MIME and etag support,
+pass a filename via filename_or_fp or
+attachment_filename.
+
+
+
Changed in version 0.12: attachment_filename is preferred over filename for MIME
+detection.
+
+
+
Changed in version 0.9: cache_timeout defaults to
+Flask.get_send_file_max_age().
+
+
+
Changed in version 0.7: MIME guessing and etag support for file-like objects was
+removed because it was unreliable. Pass a filename if you are
+able to, otherwise attach an etag yourself.
+
+
+
Changed in version 0.5: The add_etags, cache_timeout and conditional
+parameters were added. The default behavior is to add etags.
This is a secure way to serve files from a folder, such as static
+files or uploads. Uses safe_join() to
+ensure the path coming from the client is not maliciously crafted to
+point outside the specified directory.
+
If the final path does not point to an existing regular file,
+raises a 404 NotFound error.
+
+
Parameters:
+
+
directory – The directory that path must be located under,
+relative to the current application’s root path. This must not
+be a value provided by the client, otherwise it becomes insecure.
+
path – The path to the file to send, relative to
+directory.
Request contexts disappear when the response is started on the server.
+This is done for efficiency reasons and to make it less likely to encounter
+memory leaks with badly written WSGI middlewares. The downside is that if
+you are using streamed responses, the generator cannot access request bound
+information any more.
+
This function however can help you keep the context around for longer:
Generate a URL to the given endpoint with the given values.
+
This requires an active request or application context, and calls
+current_app.url_for(). See that method
+for full documentation.
+
+
Parameters:
+
+
endpoint – The endpoint name associated with the URL to
+generate. If this starts with a ., the current blueprint
+name (if any) will be used.
+
_anchor – If given, append this as #anchor to the URL.
+
_method – If given, generate the URL associated with this
+method for the endpoint.
+
_scheme – If given, the URL will have this scheme if it is
+external.
+
_external – If given, prefer the URL to be internal (False) or
+require it to be external (True). External URLs include the
+scheme and domain. When not in an active request, URLs are
+external by default.
+
values – Values to use for the variable parts of the URL rule.
+Unknown keys are appended as query string arguments, like
+?a=b&c=d.
+
+
+
+
+
Changed in version 2.2: Calls current_app.url_for, allowing an app to override the
+behavior.
+
+
+
Changed in version 0.10: The _scheme parameter was added.
+
+
+
Changed in version 0.9: The _anchor and _method parameters were added.
+
+
+
Changed in version 0.9: Calls app.handle_url_build_error on build errors.
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.
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]
+If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v
+In either case, this is followed by: for k in F: D[k] = F[k]
This session backend will set the modified and
+accessed attributes. It cannot reliably track whether a
+session is new (vs. empty), so new remains hard coded to
+False.
When data is changed, this is set to True. Only the session
+dictionary itself is tracked; if the session contains mutable
+data (for example a nested dict) then this must be set to
+True manually when modifying that data. The session cookie
+will only be written to the response if this is True.
This is called at the beginning of each request, after
+pushing the request context, before matching the URL.
+
This must return an object which implements a dictionary-like
+interface as well as the SessionMixin interface.
+
This will return None to indicate that loading failed in
+some way that is not immediately an error. The request
+context will fall back to using make_null_session()
+in this case.
This is called at the end of each request, after generating
+a response, before removing the request context. It is skipped
+if is_null_session() returns True.
A python serializer for the payload. The default is a compact
+JSON derived serializer with support for some extra Python types
+such as datetime objects or tuples.
The basic interface you have to implement in order to replace the
+default session interface which uses werkzeug’s securecookie
+implementation. The only methods you have to implement are
+open_session() and save_session(), the others have
+useful defaults which you don’t need to change.
+
The session object returned by the open_session() method has to
+provide a dictionary like interface plus the properties and methods
+from the SessionMixin. We recommend just subclassing a dict
+and adding that mixin:
+
classSession(dict,SessionMixin):
+ pass
+
+
+
If open_session() returns None Flask will call into
+make_null_session() to create a session that acts as replacement
+if the session support cannot work because some requirement is not
+fulfilled. The default NullSession class that is created
+will complain that the secret key was not set.
+
To replace the session interface on an application all you have to do
+is to assign flask.Flask.session_interface:
Multiple requests with the same session may be sent and handled
+concurrently. When implementing a new session interface, consider
+whether reads or writes to the backing store must be synchronized.
+There is no guarantee on the order in which the session for each
+request is opened or saved, it will occur in the order that requests
+begin and end processing.
The value of the Domain parameter on the session cookie. If not set,
+browsers will only send the cookie to the exact domain it was set from.
+Otherwise, they will send it to any subdomain of the given value as well.
+
Uses the SESSION_COOKIE_DOMAIN config.
+
+
Changed in version 2.3: Not set by default, does not fall back to SERVER_NAME.
Returns the path for which the cookie should be valid. The
+default implementation uses the value from the SESSION_COOKIE_PATH
+config var if it’s set, and falls back to APPLICATION_ROOT or
+uses / if it’s None.
Return 'Strict' or 'Lax' if the cookie should use the
+SameSite attribute. This currently just returns the value of
+the SESSION_COOKIE_SAMESITE setting.
A helper method that returns an expiration date for the session
+or None if the session is linked to the browser session. The
+default implementation returns now + the permanent session
+lifetime configured on the application.
Creates a null session which acts as a replacement object if the
+real session support could not be loaded due to a configuration
+error. This mainly aids the user experience because the job of the
+null session is to still support lookup without complaining but
+modifications are answered with a helpful error message of what
+failed.
make_null_session() will look here for the class that should
+be created when a null session is requested. Likewise the
+is_null_session() method will perform a typecheck against
+this type.
This is called at the beginning of each request, after
+pushing the request context, before matching the URL.
+
This must return an object which implements a dictionary-like
+interface as well as the SessionMixin interface.
+
This will return None to indicate that loading failed in
+some way that is not immediately an error. The request
+context will fall back to using make_null_session()
+in this case.
A flag that indicates if the session interface is pickle based.
+This can be used by Flask extensions to make a decision in regards
+to how to deal with the session object.
This is called at the end of each request, after generating
+a response, before removing the request context. It is skipped
+if is_null_session() returns True.
Used by session backends to determine if a Set-Cookie header
+should be set for this session cookie for this response. If the session
+has been modified, the cookie is set. If the session is permanent and
+the SESSION_REFRESH_EACH_REQUEST config is true, the cookie is
+always set.
+
This check is usually skipped if the session was deleted.
Get the template source, filename and reload helper for a template.
+It’s passed the environment and template name and has to return a
+tuple in the form (source,filename,uptodate) or raise a
+TemplateNotFound error if it can’t locate the template.
+
The source part of the returned tuple must be the source of the
+template as a string. The filename should be the name of the
+file on the filesystem if it was loaded from there, otherwise
+None. The filename is used by Python for the tracebacks
+if no loader extension is used.
+
The last item in the tuple is the uptodate function. If auto
+reloading is enabled it’s always called to check if the template
+changed. No arguments are passed so the function must store the
+old state somewhere (for example in a closure). If it returns False
+the template will be reloaded.
Works like a regular Jinja2 environment but has some additional
+knowledge of how Flask’s blueprint works so that it can prepend the
+name of the blueprint to referenced templates if necessary.
Render a template by name with the given context as a stream.
+This returns an iterator of strings, which can be used as a
+streaming response from a view.
+
+
Parameters:
+
+
template_name_or_list – The name of the template to render. If
+a list is given, the first name to exist will be rendered.
+
context – The variables to make available in the template.
Render a template from the given source string with the given
+context as a stream. This returns an iterator of strings, which can
+be used as a streaming response from a view.
+
+
Parameters:
+
+
source – The source code of the template to render.
+
context – The variables to make available in the template.
An EnvironBuilder, that takes defaults from the
+application.
+
+
Parameters:
+
+
app – The Flask application to configure the environment from.
+
path – URL path being requested.
+
base_url – Base URL where the app is being served, which
+path is relative to. If not given, built from
+PREFERRED_URL_SCHEME, subdomain,
+SERVER_NAME, and APPLICATION_ROOT.
+
subdomain – Subdomain name to append to SERVER_NAME.
+
url_scheme – Scheme to use instead of
+PREFERRED_URL_SCHEME.
+
json – If given, this is serialized as JSON and passed as
+data. Also defaults content_type to
+application/json.
+
args – other positional arguments passed to
+EnvironBuilder.
+
kwargs – other keyword arguments passed to
+EnvironBuilder.
Works like a regular Werkzeug test client but has knowledge about
+Flask’s contexts to defer the cleanup of the request context until
+the end of a with block. For general information about how to
+use this class refer to werkzeug.test.Client.
+
+
Changed in version 0.12: app.test_client() includes preset default environment, which can be
+set after instantiation of the app.test_client() object in
+client.environ_base.
Generate an environ dict from the given arguments, make a
+request to the application using it, and return the response.
+
+
Parameters:
+
+
args – Passed to EnvironBuilder to create the
+environ for the request. If a single arg is passed, it can
+be an existing EnvironBuilder or an environ dict.
+
buffered – Convert the iterator returned by the app into
+a list. If the iterator has a close() method, it is
+called automatically.
+
follow_redirects – Make additional requests to follow HTTP
+redirects until a non-redirect status is returned.
+TestResponse.history lists the intermediate
+responses.
+
+
+
+
+
Changed in version 2.1: Removed the as_tuple parameter.
+
+
+
Changed in version 2.0: The request input stream is closed when calling
+response.close(). Input streams for redirects are
+automatically closed.
+
+
+
Changed in version 0.5: If a dict is provided as file in the dict for the data
+parameter the content type has to be called content_type
+instead of mimetype. This change was made for
+consistency with werkzeug.FileWrapper.
+
+
+
Changed in version 0.5: Added the follow_redirects parameter.
When used in combination with a with statement this opens a
+session transaction. This can be used to modify the session that
+the test client uses. Once the with block is left the session is
+stored back.
Internally this is implemented by going through a temporary test
+request context and since session handling could depend on
+request variables this function accepts the same arguments as
+test_request_context() which are directly
+passed through.
Dispatches request methods to the corresponding instance methods.
+For example, if you implement a get method, it will be used to
+handle GET requests.
+
This can be useful for defining a REST API.
+
methods is automatically set based on the methods defined on
+the class.
The actual view function behavior. Subclasses must override
+this and return a valid response. Any variables from the URL
+rule are passed as keyword arguments.
Subclass this class and override dispatch_request() to
+create a generic class-based view. Call as_view() to create a
+view function that creates an instance of the class with the given
+arguments and calls its dispatch_request method with any URL
+variables.
Set methods on the class to change what methods the view
+accepts.
+
Set decorators on the class to apply a list of decorators to
+the generated view function. Decorators applied to the class itself
+will not be applied to the generated view function!
+
Set init_every_request to False for efficiency, unless
+you need to store request-global data on self.
Convert the class into a view function that can be registered
+for a route.
+
By default, the generated view will create a new instance of the
+view class for every request and call its
+dispatch_request() method. If the view class sets
+init_every_request to False, the same instance will
+be used for every request.
+
Except for name, all other arguments passed to this method
+are forwarded to the view class __init__ method.
+
+
Changed in version 2.2: Added the init_every_request class attribute.
A list of decorators to apply, in order, to the generated view
+function. Remember that @decorator syntax is applied bottom
+to top, so the first decorator in the list would be the bottom
+decorator.
The actual view function behavior. Subclasses must override
+this and return a valid response. Any variables from the URL
+rule are passed as keyword arguments.
Create a new instance of this view class for every request by
+default. If a view subclass sets this to False, the same
+instance is used for every request.
+
A single instance is more efficient, especially if complex setup
+is done during init. However, storing data on self is no
+longer safe across requests, and g should be used
+instead.
The maximum number of bytes that will be read during this request. If
+this limit is exceeded, a 413 RequestEntityTooLarge
+error is raised. If it is set to None, no limit is enforced at the
+Flask application level. However, if it is None and the request has
+no Content-Length header and the WSGI server does not indicate that
+it terminates the stream, then no data is read to avoid an infinite
+stream.
+
Each request defaults to the MAX_CONTENT_LENGTH config, which
+defaults to None. It can be set on a specific request to apply
+the limit to that specific view. This should be set appropriately based
+on an application’s or view’s specific needs.
+
+
Changed in version 3.1: This can be set per-request.
+
+
+
Changed in version 0.6: This is configurable through Flask config.
The maximum size in bytes any non-file form field may be in a
+multipart/form-data body. If this limit is exceeded, a 413
+RequestEntityTooLarge error is raised. If it
+is set to None, no limit is enforced at the Flask application level.
+
Each request defaults to the MAX_FORM_MEMORY_SIZE config, which
+defaults to 500_000. It can be set on a specific request to
+apply the limit to that specific view. This should be set appropriately
+based on an application’s or view’s specific needs.
+
+
Changed in version 3.1: This is configurable through Flask config.
The maximum number of fields that may be present in a
+multipart/form-data body. If this limit is exceeded, a 413
+RequestEntityTooLarge error is raised. If it
+is set to None, no limit is enforced at the Flask application level.
+
Each request defaults to the MAX_FORM_PARTS config, which
+defaults to 1_000. It can be set on a specific request to apply
+the limit to that specific view. This should be set appropriately based
+on an application’s or view’s specific needs.
+
+
Changed in version 3.1: This is configurable through Flask config.
If matching the URL failed, this is the exception that will be
+raised / was raised as part of the request handling. This is
+usually a NotFound exception or
+something similar.
The internal URL rule that matched the request. This can be
+useful to inspect which methods are allowed for the URL from
+a before/after handler (request.url_rule.methods) etc.
+Though if the request’s method was invalid for the URL rule,
+the valid list is available in routing_exception.valid_methods
+instead (an attribute of the Werkzeug exception
+MethodNotAllowed)
+because the request was never internally bound.
The response object that is used by default in Flask. Works like the
+response object from Werkzeug but is set to have an HTML mimetype by
+default. Quite often you don’t have to create this object yourself because
+make_response() will take care of that for you.
+
If you want to replace the response object used you can subclass this and
+set response_class to your subclass.
+
+
Changed in version 1.0: JSON support is added to the response, like the request. This is useful
+when testing to get the test client response data as JSON.
If True, or None out of debug mode, the response()
+output will not add indentation, newlines, or spaces. If False,
+or None in debug mode, it will use a non-compact representation.
Replace non-ASCII characters with escape sequences. This may be
+more compatible with some clients, but can be disabled for better
+performance and size.
Serialize the given arguments as JSON, and return a
+Response object with it. The response mimetype
+will be “application/json” and can be changed with
+mimetype.
+
If compact is False or debug mode is enabled, the
+output will be formatted to be easier to read.
+
Either positional or keyword arguments can be given, not both.
+If no arguments are given, None is serialized.
+
+
Parameters:
+
+
args – A single value to serialize, or multiple values to
+treat as a list to serialize.
Sort the keys in any serialized dicts. This may be useful for
+some caching situations, but can be disabled for better performance.
+When enabled, keys must all be strings, they are not converted
+before sorting.
A standard set of JSON operations for an application. Subclasses
+of this can be used to customize JSON behavior or use different
+JSON libraries.
+
To implement a provider for a specific library, subclass this base
+class and implement at least dumps() and loads(). All
+other methods have default implementations.
+
To use a different provider, either subclass Flask and set
+json_provider_class to a provider class, or set
+app.json to an instance of the class.
+
+
Parameters:
+
app – An application instance. This will be stored as a
+weakref.proxy on the _app attribute.
A compact representation for lossless serialization of non-standard JSON
+types. SecureCookieSessionInterface uses this
+to serialize the session data, but it may be useful in other places. It
+can be extended to support other types.
Serializer that uses a tag system to compactly represent objects that
+are not JSON types. Passed as the intermediate serializer to
+itsdangerous.Serializer.
tag_class – tag class to register. Will be instantiated with this
+serializer instance.
+
force – overwrite an existing tag. If false (default), a
+KeyError is raised.
+
index – index to insert the new tag in the tag order. Useful when
+the new tag is a special case of an existing tag. If None
+(default), the tag is appended to the end of the order.
+
+
+
Raises:
+
KeyError – if the tag key is already registered and force is
+not true.
Convert the JSON representation back to the correct type. The tag
+will already be removed.
+
+
+
+
+
Let’s see an example that adds support for
+OrderedDict. Dicts don’t have an order in JSON, so
+to handle this we will dump the items as a list of [key,value]
+pairs. Subclass JSONTag and give it the new key 'od' to
+identify the type. The session serializer processes dicts first, so
+insert the new tag at the front of the order since OrderedDict must
+be processed before dict.
Serializer that uses a tag system to compactly represent objects that
+are not JSON types. Passed as the intermediate serializer to
+itsdangerous.Serializer.
tag_class – tag class to register. Will be instantiated with this
+serializer instance.
+
force – overwrite an existing tag. If false (default), a
+KeyError is raised.
+
index – index to insert the new tag in the tag order. Useful when
+the new tag is a special case of an existing tag. If None
+(default), the tag is appended to the end of the order.
+
+
+
Raises:
+
KeyError – if the tag key is already registered and force is
+not true.
Serialize the given arguments as JSON, and return a
+Response object with the application/json
+mimetype. A dict or list returned from a view will be converted to a
+JSON response automatically without needing to call this.
+
This requires an active request or application context, and calls
+app.json.response().
+
In debug mode, the output is formatted with indentation to make it
+easier to read. This may also be controlled by the provider.
+
Either positional or keyword arguments can be given, not both.
+If no arguments are given, None is serialized.
+
+
Parameters:
+
+
args – A single value to serialize, or multiple values to
+treat as a list to serialize.
+
kwargs – Treat as a dict to serialize.
+
+
+
+
+
Changed in version 2.2: Calls current_app.json.response, allowing an app to override
+the behavior.
+
+
+
Changed in version 2.0.2: decimal.Decimal is supported by converting to a string.
+
+
+
Changed in version 0.11: Added support for serializing top-level arrays. This was a
+security risk in ancient browsers. See security-json.
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/search.html b/docs/build/html/search.html
new file mode 100644
index 00000000..e20db996
--- /dev/null
+++ b/docs/build/html/search.html
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+ Search — Flask documentation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js
new file mode 100644
index 00000000..a054f969
--- /dev/null
+++ b/docs/build/html/searchindex.js
@@ -0,0 +1 @@
+Search.setIndex({"alltitles": {"About the First Parameter": [[0, null]], "Contenido:": [[2, null]], "Flask - Documentaci\u00f3n Personalizada": [[2, null]], "Keep in Mind": [[0, null]], "Module contents": [[0, "module-flask"], [1, "module-flask.json"]], "Submodules": [[0, "submodules"], [1, "submodules"]], "Subpackages": [[0, "subpackages"]], "Tagged JSON": [[1, "tagged-json"]], "flask": [[3, null]], "flask package": [[0, null]], "flask.app module": [[0, "module-flask.app"]], "flask.blueprints module": [[0, "module-flask.blueprints"]], "flask.cli module": [[0, "module-flask.cli"]], "flask.config module": [[0, "module-flask.config"]], "flask.ctx module": [[0, "module-flask.ctx"]], "flask.debughelpers module": [[0, "module-flask.debughelpers"]], "flask.globals module": [[0, "module-flask.globals"]], "flask.helpers module": [[0, "module-flask.helpers"]], "flask.json package": [[1, null]], "flask.json.provider module": [[1, "module-flask.json.provider"]], "flask.json.tag module": [[1, "module-flask.json.tag"]], "flask.logging module": [[0, "module-flask.logging"]], "flask.sessions module": [[0, "module-flask.sessions"]], "flask.signals module": [[0, "module-flask.signals"]], "flask.templating module": [[0, "module-flask.templating"]], "flask.testing module": [[0, "module-flask.testing"]], "flask.typing module": [[0, "module-flask.typing"]], "flask.views module": [[0, "module-flask.views"]], "flask.wrappers module": [[0, "module-flask.wrappers"]]}, "docnames": ["flask", "flask.json", "index", "modules"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2}, "filenames": ["flask.rst", "flask.json.rst", "index.rst", "modules.rst"], "indexentries": {"abort() (in module flask.helpers)": [[0, "flask.helpers.abort", false]], "accessed (flask.sessions.securecookiesession attribute)": [[0, "flask.sessions.SecureCookieSession.accessed", false]], "accessed (flask.sessions.sessionmixin attribute)": [[0, "flask.sessions.SessionMixin.accessed", false]], "after_this_request() (in module flask.ctx)": [[0, "flask.ctx.after_this_request", false]], "app_context() (flask.app.flask method)": [[0, "flask.app.Flask.app_context", false]], "app_import_path (flask.cli.scriptinfo attribute)": [[0, "flask.cli.ScriptInfo.app_import_path", false]], "appcontext (class in flask.ctx)": [[0, "flask.ctx.AppContext", false]], "appgroup (class in flask.cli)": [[0, "flask.cli.AppGroup", false]], "application (flask.testing.flaskclient attribute)": [[0, "flask.testing.FlaskClient.application", false]], "as_view() (flask.views.view class method)": [[0, "flask.views.View.as_view", false]], "async_to_sync() (flask.app.flask method)": [[0, "flask.app.Flask.async_to_sync", false]], "autocorrect_location_header (flask.wrappers.response attribute)": [[0, "flask.wrappers.Response.autocorrect_location_header", false]], "blueprint (class in flask.blueprints)": [[0, "flask.blueprints.Blueprint", false]], "blueprint (flask.wrappers.request property)": [[0, "flask.wrappers.Request.blueprint", false]], "blueprints (flask.wrappers.request property)": [[0, "flask.wrappers.Request.blueprints", false]], "certparamtype (class in flask.cli)": [[0, "flask.cli.CertParamType", false]], "check() (flask.json.tag.jsontag method)": [[1, "flask.json.tag.JSONTag.check", false], [1, "id1", false]], "check() (flask.json.tag.passdict method)": [[1, "flask.json.tag.PassDict.check", false]], "check() (flask.json.tag.passlist method)": [[1, "flask.json.tag.PassList.check", false]], "check() (flask.json.tag.tagbytes method)": [[1, "flask.json.tag.TagBytes.check", false]], "check() (flask.json.tag.tagdatetime method)": [[1, "flask.json.tag.TagDateTime.check", false]], "check() (flask.json.tag.tagdict method)": [[1, "flask.json.tag.TagDict.check", false]], "check() (flask.json.tag.tagmarkup method)": [[1, "flask.json.tag.TagMarkup.check", false]], "check() (flask.json.tag.tagtuple method)": [[1, "flask.json.tag.TagTuple.check", false]], "check() (flask.json.tag.taguuid method)": [[1, "flask.json.tag.TagUUID.check", false]], "clear() (flask.sessions.nullsession method)": [[0, "flask.sessions.NullSession.clear", false]], "cli (flask.app.flask attribute)": [[0, "flask.app.Flask.cli", false]], "cli (flask.blueprints.blueprint attribute)": [[0, "flask.blueprints.Blueprint.cli", false]], "command() (flask.cli.appgroup method)": [[0, "flask.cli.AppGroup.command", false]], "compact (flask.json.provider.defaultjsonprovider attribute)": [[1, "flask.json.provider.DefaultJSONProvider.compact", false]], "config (class in flask.config)": [[0, "flask.config.Config", false]], "configattribute (class in flask.config)": [[0, "flask.config.ConfigAttribute", false]], "convert() (flask.cli.certparamtype method)": [[0, "flask.cli.CertParamType.convert", false]], "convert() (flask.cli.separatedpathtype method)": [[0, "flask.cli.SeparatedPathType.convert", false]], "copy() (flask.ctx.requestcontext method)": [[0, "flask.ctx.RequestContext.copy", false]], "copy_current_request_context() (in module flask.ctx)": [[0, "flask.ctx.copy_current_request_context", false]], "create_app (flask.cli.scriptinfo attribute)": [[0, "flask.cli.ScriptInfo.create_app", false]], "create_jinja_environment() (flask.app.flask method)": [[0, "flask.app.Flask.create_jinja_environment", false]], "create_logger() (in module flask.logging)": [[0, "flask.logging.create_logger", false]], "create_url_adapter() (flask.app.flask method)": [[0, "flask.app.Flask.create_url_adapter", false]], "data (flask.cli.scriptinfo attribute)": [[0, "flask.cli.ScriptInfo.data", false]], "debugfileskeyerror": [[0, "flask.debughelpers.DebugFilesKeyError", false]], "decorators (flask.views.view attribute)": [[0, "flask.views.View.decorators", false]], "default() (flask.json.provider.defaultjsonprovider static method)": [[1, "flask.json.provider.DefaultJSONProvider.default", false]], "default_config (flask.app.flask attribute)": [[0, "flask.app.Flask.default_config", false]], "default_handler (in module flask.logging)": [[0, "flask.logging.default_handler", false]], "default_mimetype (flask.wrappers.response attribute)": [[0, "flask.wrappers.Response.default_mimetype", false]], "default_tags (flask.json.tag.taggedjsonserializer attribute)": [[1, "flask.json.tag.TaggedJSONSerializer.default_tags", false], [1, "id7", false]], "defaultjsonprovider (class in flask.json.provider)": [[1, "flask.json.provider.DefaultJSONProvider", false]], "digest_method() (flask.sessions.securecookiesessioninterface static method)": [[0, "flask.sessions.SecureCookieSessionInterface.digest_method", false]], "dispatch_request() (flask.app.flask method)": [[0, "flask.app.Flask.dispatch_request", false]], "dispatch_request() (flask.views.methodview method)": [[0, "flask.views.MethodView.dispatch_request", false]], "dispatch_request() (flask.views.view method)": [[0, "flask.views.View.dispatch_request", false]], "dispatchingjinjaloader (class in flask.templating)": [[0, "flask.templating.DispatchingJinjaLoader", false]], "do_teardown_appcontext() (flask.app.flask method)": [[0, "flask.app.Flask.do_teardown_appcontext", false]], "do_teardown_request() (flask.app.flask method)": [[0, "flask.app.Flask.do_teardown_request", false]], "dump() (flask.json.provider.jsonprovider method)": [[1, "flask.json.provider.JSONProvider.dump", false]], "dump() (in module flask.json)": [[1, "flask.json.dump", false]], "dumps() (flask.json.provider.defaultjsonprovider method)": [[1, "flask.json.provider.DefaultJSONProvider.dumps", false]], "dumps() (flask.json.provider.jsonprovider method)": [[1, "flask.json.provider.JSONProvider.dumps", false]], "dumps() (flask.json.tag.taggedjsonserializer method)": [[1, "flask.json.tag.TaggedJSONSerializer.dumps", false], [1, "id8", false]], "dumps() (in module flask.json)": [[1, "flask.json.dumps", false]], "endpoint (flask.wrappers.request property)": [[0, "flask.wrappers.Request.endpoint", false]], "ensure_ascii (flask.json.provider.defaultjsonprovider attribute)": [[1, "flask.json.provider.DefaultJSONProvider.ensure_ascii", false]], "ensure_sync() (flask.app.flask method)": [[0, "flask.app.Flask.ensure_sync", false]], "environbuilder (class in flask.testing)": [[0, "flask.testing.EnvironBuilder", false]], "environment (class in flask.templating)": [[0, "flask.templating.Environment", false]], "environment variable": [[0, "index-0", false], [0, "index-1", false], [0, "index-2", false]], "explain_template_loading_attempts() (in module flask.debughelpers)": [[0, "flask.debughelpers.explain_template_loading_attempts", false]], "finalize_request() (flask.app.flask method)": [[0, "flask.app.Flask.finalize_request", false]], "find_app_by_string() (in module flask.cli)": [[0, "flask.cli.find_app_by_string", false]], "find_best_app() (in module flask.cli)": [[0, "flask.cli.find_best_app", false]], "flash() (in module flask.helpers)": [[0, "flask.helpers.flash", false]], "flask": [[0, "module-flask", false]], "flask (class in flask.app)": [[0, "flask.app.Flask", false]], "flask.app": [[0, "module-flask.app", false]], "flask.blueprints": [[0, "module-flask.blueprints", false]], "flask.cli": [[0, "module-flask.cli", false]], "flask.config": [[0, "module-flask.config", false]], "flask.ctx": [[0, "module-flask.ctx", false]], "flask.debughelpers": [[0, "module-flask.debughelpers", false]], "flask.globals": [[0, "module-flask.globals", false]], "flask.helpers": [[0, "module-flask.helpers", false]], "flask.json": [[1, "module-flask.json", false]], "flask.json.provider": [[1, "module-flask.json.provider", false]], "flask.json.tag": [[1, "module-flask.json.tag", false]], "flask.logging": [[0, "module-flask.logging", false]], "flask.sessions": [[0, "module-flask.sessions", false]], "flask.signals": [[0, "module-flask.signals", false]], "flask.templating": [[0, "module-flask.templating", false]], "flask.testing": [[0, "module-flask.testing", false]], "flask.typing": [[0, "module-flask.typing", false]], "flask.views": [[0, "module-flask.views", false]], "flask.wrappers": [[0, "module-flask.wrappers", false]], "flask_debug": [[0, "index-0", false], [0, "index-1", false]], "flask_skip_dotenv": [[0, "index-2", false]], "flaskclient (class in flask.testing)": [[0, "flask.testing.FlaskClient", false]], "flaskclirunner (class in flask.testing)": [[0, "flask.testing.FlaskCliRunner", false]], "flaskgroup (class in flask.cli)": [[0, "flask.cli.FlaskGroup", false]], "formdataroutingredirect": [[0, "flask.debughelpers.FormDataRoutingRedirect", false]], "from_envvar() (flask.config.config method)": [[0, "flask.config.Config.from_envvar", false]], "from_file() (flask.config.config method)": [[0, "flask.config.Config.from_file", false]], "from_mapping() (flask.config.config method)": [[0, "flask.config.Config.from_mapping", false]], "from_object() (flask.config.config method)": [[0, "flask.config.Config.from_object", false]], "from_prefixed_env() (flask.config.config method)": [[0, "flask.config.Config.from_prefixed_env", false]], "from_pyfile() (flask.config.config method)": [[0, "flask.config.Config.from_pyfile", false]], "full_dispatch_request() (flask.app.flask method)": [[0, "flask.app.Flask.full_dispatch_request", false]], "get() (flask.sessions.securecookiesession method)": [[0, "flask.sessions.SecureCookieSession.get", false]], "get_command() (flask.cli.flaskgroup method)": [[0, "flask.cli.FlaskGroup.get_command", false]], "get_cookie_domain() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_domain", false]], "get_cookie_httponly() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_httponly", false]], "get_cookie_name() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_name", false]], "get_cookie_partitioned() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_partitioned", false]], "get_cookie_path() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_path", false]], "get_cookie_samesite() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_samesite", false]], "get_cookie_secure() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_cookie_secure", false]], "get_debug_flag() (in module flask.helpers)": [[0, "flask.helpers.get_debug_flag", false]], "get_expiration_time() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.get_expiration_time", false]], "get_flashed_messages() (in module flask.helpers)": [[0, "flask.helpers.get_flashed_messages", false]], "get_load_dotenv() (in module flask.helpers)": [[0, "flask.helpers.get_load_dotenv", false]], "get_namespace() (flask.config.config method)": [[0, "flask.config.Config.get_namespace", false]], "get_send_file_max_age() (flask.app.flask method)": [[0, "flask.app.Flask.get_send_file_max_age", false]], "get_send_file_max_age() (flask.blueprints.blueprint method)": [[0, "flask.blueprints.Blueprint.get_send_file_max_age", false]], "get_signing_serializer() (flask.sessions.securecookiesessioninterface method)": [[0, "flask.sessions.SecureCookieSessionInterface.get_signing_serializer", false]], "get_source() (flask.templating.dispatchingjinjaloader method)": [[0, "flask.templating.DispatchingJinjaLoader.get_source", false]], "get_template_attribute() (in module flask.helpers)": [[0, "flask.helpers.get_template_attribute", false]], "get_version() (in module flask.cli)": [[0, "flask.cli.get_version", false]], "group() (flask.cli.appgroup method)": [[0, "flask.cli.AppGroup.group", false]], "handle_exception() (flask.app.flask method)": [[0, "flask.app.Flask.handle_exception", false]], "handle_http_exception() (flask.app.flask method)": [[0, "flask.app.Flask.handle_http_exception", false]], "handle_user_exception() (flask.app.flask method)": [[0, "flask.app.Flask.handle_user_exception", false]], "has_app_context() (in module flask.ctx)": [[0, "flask.ctx.has_app_context", false]], "has_level_handler() (in module flask.logging)": [[0, "flask.logging.has_level_handler", false]], "has_request_context() (in module flask.ctx)": [[0, "flask.ctx.has_request_context", false]], "init_every_request (flask.views.view attribute)": [[0, "flask.views.View.init_every_request", false]], "invoke() (flask.testing.flaskclirunner method)": [[0, "flask.testing.FlaskCliRunner.invoke", false]], "is_null_session() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.is_null_session", false]], "json_dumps() (flask.testing.environbuilder method)": [[0, "flask.testing.EnvironBuilder.json_dumps", false]], "json_module (flask.wrappers.request attribute)": [[0, "flask.wrappers.Request.json_module", false]], "json_module (flask.wrappers.response attribute)": [[0, "flask.wrappers.Response.json_module", false]], "jsonify() (in module flask.json)": [[1, "flask.json.jsonify", false]], "jsonprovider (class in flask.json.provider)": [[1, "flask.json.provider.JSONProvider", false]], "jsontag (class in flask.json.tag)": [[1, "flask.json.tag.JSONTag", false], [1, "id0", false]], "key (flask.json.tag.jsontag attribute)": [[1, "flask.json.tag.JSONTag.key", false], [1, "id2", false]], "key (flask.json.tag.tagbytes attribute)": [[1, "flask.json.tag.TagBytes.key", false]], "key (flask.json.tag.tagdatetime attribute)": [[1, "flask.json.tag.TagDateTime.key", false]], "key (flask.json.tag.tagdict attribute)": [[1, "flask.json.tag.TagDict.key", false]], "key (flask.json.tag.tagmarkup attribute)": [[1, "flask.json.tag.TagMarkup.key", false]], "key (flask.json.tag.tagtuple attribute)": [[1, "flask.json.tag.TagTuple.key", false]], "key (flask.json.tag.taguuid attribute)": [[1, "flask.json.tag.TagUUID.key", false]], "key_derivation (flask.sessions.securecookiesessioninterface attribute)": [[0, "flask.sessions.SecureCookieSessionInterface.key_derivation", false]], "list_commands() (flask.cli.flaskgroup method)": [[0, "flask.cli.FlaskGroup.list_commands", false]], "list_templates() (flask.templating.dispatchingjinjaloader method)": [[0, "flask.templating.DispatchingJinjaLoader.list_templates", false]], "load() (flask.json.provider.jsonprovider method)": [[1, "flask.json.provider.JSONProvider.load", false]], "load() (in module flask.json)": [[1, "flask.json.load", false]], "load_app() (flask.cli.scriptinfo method)": [[0, "flask.cli.ScriptInfo.load_app", false]], "load_dotenv() (in module flask.cli)": [[0, "flask.cli.load_dotenv", false]], "load_dotenv_defaults (flask.cli.scriptinfo attribute)": [[0, "flask.cli.ScriptInfo.load_dotenv_defaults", false]], "loads() (flask.json.provider.defaultjsonprovider method)": [[1, "flask.json.provider.DefaultJSONProvider.loads", false]], "loads() (flask.json.provider.jsonprovider method)": [[1, "flask.json.provider.JSONProvider.loads", false]], "loads() (flask.json.tag.taggedjsonserializer method)": [[1, "flask.json.tag.TaggedJSONSerializer.loads", false], [1, "id9", false]], "loads() (in module flask.json)": [[1, "flask.json.loads", false]], "locate_app() (in module flask.cli)": [[0, "flask.cli.locate_app", false]], "log_exception() (flask.app.flask method)": [[0, "flask.app.Flask.log_exception", false]], "main() (in module flask.cli)": [[0, "flask.cli.main", false]], "make_context() (flask.cli.flaskgroup method)": [[0, "flask.cli.FlaskGroup.make_context", false]], "make_default_options_response() (flask.app.flask method)": [[0, "flask.app.Flask.make_default_options_response", false]], "make_null_session() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.make_null_session", false]], "make_response() (flask.app.flask method)": [[0, "flask.app.Flask.make_response", false]], "make_response() (in module flask.helpers)": [[0, "flask.helpers.make_response", false]], "make_shell_context() (flask.app.flask method)": [[0, "flask.app.Flask.make_shell_context", false]], "match_request() (flask.ctx.requestcontext method)": [[0, "flask.ctx.RequestContext.match_request", false]], "max_content_length (flask.wrappers.request property)": [[0, "flask.wrappers.Request.max_content_length", false]], "max_cookie_size (flask.wrappers.response property)": [[0, "flask.wrappers.Response.max_cookie_size", false]], "max_form_memory_size (flask.wrappers.request property)": [[0, "flask.wrappers.Request.max_form_memory_size", false]], "max_form_parts (flask.wrappers.request property)": [[0, "flask.wrappers.Request.max_form_parts", false]], "methods (flask.views.view attribute)": [[0, "flask.views.View.methods", false]], "methodview (class in flask.views)": [[0, "flask.views.MethodView", false]], "mimetype (flask.json.provider.defaultjsonprovider attribute)": [[1, "flask.json.provider.DefaultJSONProvider.mimetype", false]], "modified (flask.sessions.securecookiesession attribute)": [[0, "flask.sessions.SecureCookieSession.modified", false]], "modified (flask.sessions.sessionmixin attribute)": [[0, "flask.sessions.SessionMixin.modified", false]], "module": [[0, "module-flask", false], [0, "module-flask.app", false], [0, "module-flask.blueprints", false], [0, "module-flask.cli", false], [0, "module-flask.config", false], [0, "module-flask.ctx", false], [0, "module-flask.debughelpers", false], [0, "module-flask.globals", false], [0, "module-flask.helpers", false], [0, "module-flask.logging", false], [0, "module-flask.sessions", false], [0, "module-flask.signals", false], [0, "module-flask.templating", false], [0, "module-flask.testing", false], [0, "module-flask.typing", false], [0, "module-flask.views", false], [0, "module-flask.wrappers", false], [1, "module-flask.json", false], [1, "module-flask.json.provider", false], [1, "module-flask.json.tag", false]], "name (flask.cli.certparamtype attribute)": [[0, "flask.cli.CertParamType.name", false]], "new (flask.sessions.sessionmixin attribute)": [[0, "flask.sessions.SessionMixin.new", false]], "noappexception": [[0, "flask.cli.NoAppException", false]], "null_session_class (flask.sessions.sessioninterface attribute)": [[0, "flask.sessions.SessionInterface.null_session_class", false]], "nullsession (class in flask.sessions)": [[0, "flask.sessions.NullSession", false]], "on_json_loading_failed() (flask.wrappers.request method)": [[0, "flask.wrappers.Request.on_json_loading_failed", false]], "open() (flask.testing.flaskclient method)": [[0, "flask.testing.FlaskClient.open", false]], "open_instance_resource() (flask.app.flask method)": [[0, "flask.app.Flask.open_instance_resource", false]], "open_resource() (flask.app.flask method)": [[0, "flask.app.Flask.open_resource", false]], "open_resource() (flask.blueprints.blueprint method)": [[0, "flask.blueprints.Blueprint.open_resource", false]], "open_session() (flask.sessions.securecookiesessioninterface method)": [[0, "flask.sessions.SecureCookieSessionInterface.open_session", false]], "open_session() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.open_session", false]], "order (flask.json.tag.taggedjsonserializer attribute)": [[1, "flask.json.tag.TaggedJSONSerializer.order", false]], "parse_args() (flask.cli.flaskgroup method)": [[0, "flask.cli.FlaskGroup.parse_args", false]], "passdict (class in flask.json.tag)": [[1, "flask.json.tag.PassDict", false]], "passlist (class in flask.json.tag)": [[1, "flask.json.tag.PassList", false]], "permanent (flask.sessions.sessionmixin property)": [[0, "flask.sessions.SessionMixin.permanent", false]], "pickle_based (flask.sessions.sessioninterface attribute)": [[0, "flask.sessions.SessionInterface.pickle_based", false]], "pop() (flask.ctx.appcontext method)": [[0, "flask.ctx.AppContext.pop", false]], "pop() (flask.ctx.requestcontext method)": [[0, "flask.ctx.RequestContext.pop", false]], "pop() (flask.sessions.nullsession method)": [[0, "flask.sessions.NullSession.pop", false]], "popitem() (flask.sessions.nullsession method)": [[0, "flask.sessions.NullSession.popitem", false]], "prepare_import() (in module flask.cli)": [[0, "flask.cli.prepare_import", false]], "preprocess_request() (flask.app.flask method)": [[0, "flask.app.Flask.preprocess_request", false]], "process_response() (flask.app.flask method)": [[0, "flask.app.Flask.process_response", false]], "provide_automatic_options (flask.views.view attribute)": [[0, "flask.views.View.provide_automatic_options", false]], "push() (flask.ctx.appcontext method)": [[0, "flask.ctx.AppContext.push", false]], "push() (flask.ctx.requestcontext method)": [[0, "flask.ctx.RequestContext.push", false]], "redirect() (in module flask.helpers)": [[0, "flask.helpers.redirect", false]], "register() (flask.json.tag.taggedjsonserializer method)": [[1, "flask.json.tag.TaggedJSONSerializer.register", false], [1, "id10", false]], "render_template() (in module flask.templating)": [[0, "flask.templating.render_template", false]], "render_template_string() (in module flask.templating)": [[0, "flask.templating.render_template_string", false]], "request (class in flask.wrappers)": [[0, "flask.wrappers.Request", false]], "request_class (flask.app.flask attribute)": [[0, "flask.app.Flask.request_class", false]], "request_context() (flask.app.flask method)": [[0, "flask.app.Flask.request_context", false]], "requestcontext (class in flask.ctx)": [[0, "flask.ctx.RequestContext", false]], "response (class in flask.wrappers)": [[0, "flask.wrappers.Response", false]], "response() (flask.json.provider.defaultjsonprovider method)": [[1, "flask.json.provider.DefaultJSONProvider.response", false]], "response() (flask.json.provider.jsonprovider method)": [[1, "flask.json.provider.JSONProvider.response", false]], "response_class (flask.app.flask attribute)": [[0, "flask.app.Flask.response_class", false]], "rfc": [[0, "index-3", false], [1, "index-0", false]], "rfc 2231": [[0, "index-3", false]], "rfc 822": [[1, "index-0", false]], "routing_exception (flask.wrappers.request attribute)": [[0, "flask.wrappers.Request.routing_exception", false]], "run() (flask.app.flask method)": [[0, "flask.app.Flask.run", false]], "salt (flask.sessions.securecookiesessioninterface attribute)": [[0, "flask.sessions.SecureCookieSessionInterface.salt", false]], "save_session() (flask.sessions.securecookiesessioninterface method)": [[0, "flask.sessions.SecureCookieSessionInterface.save_session", false]], "save_session() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.save_session", false]], "scriptinfo (class in flask.cli)": [[0, "flask.cli.ScriptInfo", false]], "securecookiesession (class in flask.sessions)": [[0, "flask.sessions.SecureCookieSession", false]], "securecookiesessioninterface (class in flask.sessions)": [[0, "flask.sessions.SecureCookieSessionInterface", false]], "send_file() (in module flask.helpers)": [[0, "flask.helpers.send_file", false]], "send_from_directory() (in module flask.helpers)": [[0, "flask.helpers.send_from_directory", false]], "send_static_file() (flask.app.flask method)": [[0, "flask.app.Flask.send_static_file", false]], "send_static_file() (flask.blueprints.blueprint method)": [[0, "flask.blueprints.Blueprint.send_static_file", false]], "separatedpathtype (class in flask.cli)": [[0, "flask.cli.SeparatedPathType", false]], "serializer (flask.json.tag.jsontag attribute)": [[1, "flask.json.tag.JSONTag.serializer", false]], "serializer (flask.sessions.securecookiesessioninterface attribute)": [[0, "flask.sessions.SecureCookieSessionInterface.serializer", false]], "session_class (flask.sessions.securecookiesessioninterface attribute)": [[0, "flask.sessions.SecureCookieSessionInterface.session_class", false]], "session_interface (flask.app.flask attribute)": [[0, "flask.app.Flask.session_interface", false]], "session_transaction() (flask.testing.flaskclient method)": [[0, "flask.testing.FlaskClient.session_transaction", false]], "sessioninterface (class in flask.sessions)": [[0, "flask.sessions.SessionInterface", false]], "sessionmixin (class in flask.sessions)": [[0, "flask.sessions.SessionMixin", false]], "setdefault() (flask.sessions.nullsession method)": [[0, "flask.sessions.NullSession.setdefault", false]], "setdefault() (flask.sessions.securecookiesession method)": [[0, "flask.sessions.SecureCookieSession.setdefault", false]], "should_set_cookie() (flask.sessions.sessioninterface method)": [[0, "flask.sessions.SessionInterface.should_set_cookie", false]], "show_server_banner() (in module flask.cli)": [[0, "flask.cli.show_server_banner", false]], "sort_keys (flask.json.provider.defaultjsonprovider attribute)": [[1, "flask.json.provider.DefaultJSONProvider.sort_keys", false]], "stream_template() (in module flask.templating)": [[0, "flask.templating.stream_template", false]], "stream_template_string() (in module flask.templating)": [[0, "flask.templating.stream_template_string", false]], "stream_with_context() (in module flask.helpers)": [[0, "flask.helpers.stream_with_context", false]], "tag() (flask.json.tag.jsontag method)": [[1, "flask.json.tag.JSONTag.tag", false], [1, "id3", false]], "tag() (flask.json.tag.passdict method)": [[1, "flask.json.tag.PassDict.tag", false]], "tag() (flask.json.tag.passlist method)": [[1, "flask.json.tag.PassList.tag", false]], "tag() (flask.json.tag.taggedjsonserializer method)": [[1, "flask.json.tag.TaggedJSONSerializer.tag", false], [1, "id11", false]], "tagbytes (class in flask.json.tag)": [[1, "flask.json.tag.TagBytes", false]], "tagdatetime (class in flask.json.tag)": [[1, "flask.json.tag.TagDateTime", false]], "tagdict (class in flask.json.tag)": [[1, "flask.json.tag.TagDict", false]], "taggedjsonserializer (class in flask.json.tag)": [[1, "flask.json.tag.TaggedJSONSerializer", false], [1, "id6", false]], "tagmarkup (class in flask.json.tag)": [[1, "flask.json.tag.TagMarkup", false]], "tags (flask.json.tag.taggedjsonserializer attribute)": [[1, "flask.json.tag.TaggedJSONSerializer.tags", false]], "tagtuple (class in flask.json.tag)": [[1, "flask.json.tag.TagTuple", false]], "taguuid (class in flask.json.tag)": [[1, "flask.json.tag.TagUUID", false]], "test_cli_runner() (flask.app.flask method)": [[0, "flask.app.Flask.test_cli_runner", false]], "test_client() (flask.app.flask method)": [[0, "flask.app.Flask.test_client", false]], "test_request_context() (flask.app.flask method)": [[0, "flask.app.Flask.test_request_context", false]], "to_json() (flask.json.tag.jsontag method)": [[1, "flask.json.tag.JSONTag.to_json", false], [1, "id4", false]], "to_json() (flask.json.tag.passdict method)": [[1, "flask.json.tag.PassDict.to_json", false]], "to_json() (flask.json.tag.passlist method)": [[1, "flask.json.tag.PassList.to_json", false]], "to_json() (flask.json.tag.tagbytes method)": [[1, "flask.json.tag.TagBytes.to_json", false]], "to_json() (flask.json.tag.tagdatetime method)": [[1, "flask.json.tag.TagDateTime.to_json", false]], "to_json() (flask.json.tag.tagdict method)": [[1, "flask.json.tag.TagDict.to_json", false]], "to_json() (flask.json.tag.tagmarkup method)": [[1, "flask.json.tag.TagMarkup.to_json", false]], "to_json() (flask.json.tag.tagtuple method)": [[1, "flask.json.tag.TagTuple.to_json", false]], "to_json() (flask.json.tag.taguuid method)": [[1, "flask.json.tag.TagUUID.to_json", false]], "to_python() (flask.json.tag.jsontag method)": [[1, "flask.json.tag.JSONTag.to_python", false], [1, "id5", false]], "to_python() (flask.json.tag.tagbytes method)": [[1, "flask.json.tag.TagBytes.to_python", false]], "to_python() (flask.json.tag.tagdatetime method)": [[1, "flask.json.tag.TagDateTime.to_python", false]], "to_python() (flask.json.tag.tagdict method)": [[1, "flask.json.tag.TagDict.to_python", false]], "to_python() (flask.json.tag.tagmarkup method)": [[1, "flask.json.tag.TagMarkup.to_python", false]], "to_python() (flask.json.tag.tagtuple method)": [[1, "flask.json.tag.TagTuple.to_python", false]], "to_python() (flask.json.tag.taguuid method)": [[1, "flask.json.tag.TagUUID.to_python", false]], "unexpectedunicodeerror": [[0, "flask.debughelpers.UnexpectedUnicodeError", false]], "untag() (flask.json.tag.taggedjsonserializer method)": [[1, "flask.json.tag.TaggedJSONSerializer.untag", false], [1, "id12", false]], "update() (flask.sessions.nullsession method)": [[0, "flask.sessions.NullSession.update", false]], "update_template_context() (flask.app.flask method)": [[0, "flask.app.Flask.update_template_context", false]], "url_for() (flask.app.flask method)": [[0, "flask.app.Flask.url_for", false]], "url_for() (in module flask.helpers)": [[0, "flask.helpers.url_for", false]], "url_rule (flask.wrappers.request attribute)": [[0, "flask.wrappers.Request.url_rule", false]], "view (class in flask.views)": [[0, "flask.views.View", false]], "view_args (flask.wrappers.request attribute)": [[0, "flask.wrappers.Request.view_args", false]], "with_appcontext() (in module flask.cli)": [[0, "flask.cli.with_appcontext", false]], "wsgi_app() (flask.app.flask method)": [[0, "flask.app.Flask.wsgi_app", false]]}, "objects": {"": [[0, 0, 0, "-", "flask"]], "flask": [[0, 0, 0, "-", "app"], [0, 0, 0, "-", "blueprints"], [0, 0, 0, "-", "cli"], [0, 0, 0, "-", "config"], [0, 0, 0, "-", "ctx"], [0, 0, 0, "-", "debughelpers"], [0, 0, 0, "-", "globals"], [0, 0, 0, "-", "helpers"], [1, 0, 0, "-", "json"], [0, 0, 0, "-", "logging"], [0, 0, 0, "-", "sessions"], [0, 0, 0, "-", "signals"], [0, 0, 0, "-", "templating"], [0, 0, 0, "-", "testing"], [0, 0, 0, "-", "typing"], [0, 0, 0, "-", "views"], [0, 0, 0, "-", "wrappers"]], "flask.app": [[0, 1, 1, "", "Flask"]], "flask.app.Flask": [[0, 2, 1, "", "app_context"], [0, 2, 1, "", "async_to_sync"], [0, 3, 1, "", "cli"], [0, 2, 1, "", "create_jinja_environment"], [0, 2, 1, "", "create_url_adapter"], [0, 3, 1, "", "default_config"], [0, 2, 1, "", "dispatch_request"], [0, 2, 1, "", "do_teardown_appcontext"], [0, 2, 1, "", "do_teardown_request"], [0, 2, 1, "", "ensure_sync"], [0, 2, 1, "", "finalize_request"], [0, 2, 1, "", "full_dispatch_request"], [0, 2, 1, "", "get_send_file_max_age"], [0, 2, 1, "", "handle_exception"], [0, 2, 1, "", "handle_http_exception"], [0, 2, 1, "", "handle_user_exception"], [0, 2, 1, "", "log_exception"], [0, 2, 1, "", "make_default_options_response"], [0, 2, 1, "", "make_response"], [0, 2, 1, "", "make_shell_context"], [0, 2, 1, "", "open_instance_resource"], [0, 2, 1, "", "open_resource"], [0, 2, 1, "", "preprocess_request"], [0, 2, 1, "", "process_response"], [0, 3, 1, "", "request_class"], [0, 2, 1, "", "request_context"], [0, 3, 1, "", "response_class"], [0, 2, 1, "", "run"], [0, 2, 1, "", "send_static_file"], [0, 3, 1, "", "session_interface"], [0, 2, 1, "", "test_cli_runner"], [0, 2, 1, "", "test_client"], [0, 2, 1, "", "test_request_context"], [0, 2, 1, "", "update_template_context"], [0, 2, 1, "", "url_for"], [0, 2, 1, "", "wsgi_app"]], "flask.blueprints": [[0, 1, 1, "", "Blueprint"]], "flask.blueprints.Blueprint": [[0, 3, 1, "", "cli"], [0, 2, 1, "", "get_send_file_max_age"], [0, 2, 1, "", "open_resource"], [0, 2, 1, "", "send_static_file"]], "flask.cli": [[0, 1, 1, "", "AppGroup"], [0, 1, 1, "", "CertParamType"], [0, 1, 1, "", "FlaskGroup"], [0, 4, 1, "", "NoAppException"], [0, 1, 1, "", "ScriptInfo"], [0, 1, 1, "", "SeparatedPathType"], [0, 5, 1, "", "find_app_by_string"], [0, 5, 1, "", "find_best_app"], [0, 5, 1, "", "get_version"], [0, 5, 1, "", "load_dotenv"], [0, 5, 1, "", "locate_app"], [0, 5, 1, "", "main"], [0, 5, 1, "", "prepare_import"], [0, 5, 1, "", "show_server_banner"], [0, 5, 1, "", "with_appcontext"]], "flask.cli.AppGroup": [[0, 2, 1, "", "command"], [0, 2, 1, "", "group"]], "flask.cli.CertParamType": [[0, 2, 1, "", "convert"], [0, 3, 1, "", "name"]], "flask.cli.FlaskGroup": [[0, 2, 1, "", "get_command"], [0, 2, 1, "", "list_commands"], [0, 2, 1, "", "make_context"], [0, 2, 1, "", "parse_args"]], "flask.cli.ScriptInfo": [[0, 3, 1, "", "app_import_path"], [0, 3, 1, "", "create_app"], [0, 3, 1, "", "data"], [0, 2, 1, "", "load_app"], [0, 3, 1, "", "load_dotenv_defaults"]], "flask.cli.SeparatedPathType": [[0, 2, 1, "", "convert"]], "flask.config": [[0, 1, 1, "", "Config"], [0, 1, 1, "", "ConfigAttribute"]], "flask.config.Config": [[0, 2, 1, "", "from_envvar"], [0, 2, 1, "", "from_file"], [0, 2, 1, "", "from_mapping"], [0, 2, 1, "", "from_object"], [0, 2, 1, "", "from_prefixed_env"], [0, 2, 1, "", "from_pyfile"], [0, 2, 1, "", "get_namespace"]], "flask.ctx": [[0, 1, 1, "", "AppContext"], [0, 1, 1, "", "RequestContext"], [0, 5, 1, "", "after_this_request"], [0, 5, 1, "", "copy_current_request_context"], [0, 5, 1, "", "has_app_context"], [0, 5, 1, "", "has_request_context"]], "flask.ctx.AppContext": [[0, 2, 1, "", "pop"], [0, 2, 1, "", "push"]], "flask.ctx.RequestContext": [[0, 2, 1, "", "copy"], [0, 2, 1, "", "match_request"], [0, 2, 1, "", "pop"], [0, 2, 1, "", "push"]], "flask.debughelpers": [[0, 4, 1, "", "DebugFilesKeyError"], [0, 4, 1, "", "FormDataRoutingRedirect"], [0, 4, 1, "", "UnexpectedUnicodeError"], [0, 5, 1, "", "explain_template_loading_attempts"]], "flask.helpers": [[0, 5, 1, "", "abort"], [0, 5, 1, "", "flash"], [0, 5, 1, "", "get_debug_flag"], [0, 5, 1, "", "get_flashed_messages"], [0, 5, 1, "", "get_load_dotenv"], [0, 5, 1, "", "get_template_attribute"], [0, 5, 1, "", "make_response"], [0, 5, 1, "", "redirect"], [0, 5, 1, "", "send_file"], [0, 5, 1, "", "send_from_directory"], [0, 5, 1, "", "stream_with_context"], [0, 5, 1, "", "url_for"]], "flask.json": [[1, 5, 1, "", "dump"], [1, 5, 1, "", "dumps"], [1, 5, 1, "", "jsonify"], [1, 5, 1, "", "load"], [1, 5, 1, "", "loads"], [1, 0, 0, "-", "provider"], [1, 0, 0, "-", "tag"]], "flask.json.provider": [[1, 1, 1, "", "DefaultJSONProvider"], [1, 1, 1, "", "JSONProvider"]], "flask.json.provider.DefaultJSONProvider": [[1, 3, 1, "", "compact"], [1, 2, 1, "", "default"], [1, 2, 1, "", "dumps"], [1, 3, 1, "", "ensure_ascii"], [1, 2, 1, "", "loads"], [1, 3, 1, "", "mimetype"], [1, 2, 1, "", "response"], [1, 3, 1, "", "sort_keys"]], "flask.json.provider.JSONProvider": [[1, 2, 1, "", "dump"], [1, 2, 1, "", "dumps"], [1, 2, 1, "", "load"], [1, 2, 1, "", "loads"], [1, 2, 1, "", "response"]], "flask.json.tag": [[1, 1, 1, "id0", "JSONTag"], [1, 1, 1, "", "PassDict"], [1, 1, 1, "", "PassList"], [1, 1, 1, "", "TagBytes"], [1, 1, 1, "", "TagDateTime"], [1, 1, 1, "", "TagDict"], [1, 1, 1, "", "TagMarkup"], [1, 1, 1, "", "TagTuple"], [1, 1, 1, "", "TagUUID"], [1, 1, 1, "id6", "TaggedJSONSerializer"]], "flask.json.tag.JSONTag": [[1, 2, 1, "id1", "check"], [1, 3, 1, "id2", "key"], [1, 3, 1, "", "serializer"], [1, 2, 1, "id3", "tag"], [1, 2, 1, "id4", "to_json"], [1, 2, 1, "id5", "to_python"]], "flask.json.tag.PassDict": [[1, 2, 1, "", "check"], [1, 2, 1, "", "tag"], [1, 2, 1, "", "to_json"]], "flask.json.tag.PassList": [[1, 2, 1, "", "check"], [1, 2, 1, "", "tag"], [1, 2, 1, "", "to_json"]], "flask.json.tag.TagBytes": [[1, 2, 1, "", "check"], [1, 3, 1, "", "key"], [1, 2, 1, "", "to_json"], [1, 2, 1, "", "to_python"]], "flask.json.tag.TagDateTime": [[1, 2, 1, "", "check"], [1, 3, 1, "", "key"], [1, 2, 1, "", "to_json"], [1, 2, 1, "", "to_python"]], "flask.json.tag.TagDict": [[1, 2, 1, "", "check"], [1, 3, 1, "", "key"], [1, 2, 1, "", "to_json"], [1, 2, 1, "", "to_python"]], "flask.json.tag.TagMarkup": [[1, 2, 1, "", "check"], [1, 3, 1, "", "key"], [1, 2, 1, "", "to_json"], [1, 2, 1, "", "to_python"]], "flask.json.tag.TagTuple": [[1, 2, 1, "", "check"], [1, 3, 1, "", "key"], [1, 2, 1, "", "to_json"], [1, 2, 1, "", "to_python"]], "flask.json.tag.TagUUID": [[1, 2, 1, "", "check"], [1, 3, 1, "", "key"], [1, 2, 1, "", "to_json"], [1, 2, 1, "", "to_python"]], "flask.json.tag.TaggedJSONSerializer": [[1, 3, 1, "id7", "default_tags"], [1, 2, 1, "id8", "dumps"], [1, 2, 1, "id9", "loads"], [1, 3, 1, "", "order"], [1, 2, 1, "id10", "register"], [1, 2, 1, "id11", "tag"], [1, 3, 1, "", "tags"], [1, 2, 1, "id12", "untag"]], "flask.logging": [[0, 5, 1, "", "create_logger"], [0, 6, 1, "", "default_handler"], [0, 5, 1, "", "has_level_handler"]], "flask.sessions": [[0, 1, 1, "", "NullSession"], [0, 1, 1, "", "SecureCookieSession"], [0, 1, 1, "", "SecureCookieSessionInterface"], [0, 1, 1, "", "SessionInterface"], [0, 1, 1, "", "SessionMixin"]], "flask.sessions.NullSession": [[0, 2, 1, "", "clear"], [0, 2, 1, "", "pop"], [0, 2, 1, "", "popitem"], [0, 2, 1, "", "setdefault"], [0, 2, 1, "", "update"]], "flask.sessions.SecureCookieSession": [[0, 3, 1, "", "accessed"], [0, 2, 1, "", "get"], [0, 3, 1, "", "modified"], [0, 2, 1, "", "setdefault"]], "flask.sessions.SecureCookieSessionInterface": [[0, 2, 1, "", "digest_method"], [0, 2, 1, "", "get_signing_serializer"], [0, 3, 1, "", "key_derivation"], [0, 2, 1, "", "open_session"], [0, 3, 1, "", "salt"], [0, 2, 1, "", "save_session"], [0, 3, 1, "", "serializer"], [0, 3, 1, "", "session_class"]], "flask.sessions.SessionInterface": [[0, 2, 1, "", "get_cookie_domain"], [0, 2, 1, "", "get_cookie_httponly"], [0, 2, 1, "", "get_cookie_name"], [0, 2, 1, "", "get_cookie_partitioned"], [0, 2, 1, "", "get_cookie_path"], [0, 2, 1, "", "get_cookie_samesite"], [0, 2, 1, "", "get_cookie_secure"], [0, 2, 1, "", "get_expiration_time"], [0, 2, 1, "", "is_null_session"], [0, 2, 1, "", "make_null_session"], [0, 3, 1, "", "null_session_class"], [0, 2, 1, "", "open_session"], [0, 3, 1, "", "pickle_based"], [0, 2, 1, "", "save_session"], [0, 2, 1, "", "should_set_cookie"]], "flask.sessions.SessionMixin": [[0, 3, 1, "", "accessed"], [0, 3, 1, "", "modified"], [0, 3, 1, "", "new"], [0, 7, 1, "", "permanent"]], "flask.templating": [[0, 1, 1, "", "DispatchingJinjaLoader"], [0, 1, 1, "", "Environment"], [0, 5, 1, "", "render_template"], [0, 5, 1, "", "render_template_string"], [0, 5, 1, "", "stream_template"], [0, 5, 1, "", "stream_template_string"]], "flask.templating.DispatchingJinjaLoader": [[0, 2, 1, "", "get_source"], [0, 2, 1, "", "list_templates"]], "flask.testing": [[0, 1, 1, "", "EnvironBuilder"], [0, 1, 1, "", "FlaskCliRunner"], [0, 1, 1, "", "FlaskClient"]], "flask.testing.EnvironBuilder": [[0, 2, 1, "", "json_dumps"]], "flask.testing.FlaskCliRunner": [[0, 2, 1, "", "invoke"]], "flask.testing.FlaskClient": [[0, 3, 1, "", "application"], [0, 2, 1, "", "open"], [0, 2, 1, "", "session_transaction"]], "flask.views": [[0, 1, 1, "", "MethodView"], [0, 1, 1, "", "View"]], "flask.views.MethodView": [[0, 2, 1, "", "dispatch_request"]], "flask.views.View": [[0, 2, 1, "", "as_view"], [0, 3, 1, "", "decorators"], [0, 2, 1, "", "dispatch_request"], [0, 3, 1, "", "init_every_request"], [0, 3, 1, "", "methods"], [0, 3, 1, "", "provide_automatic_options"]], "flask.wrappers": [[0, 1, 1, "", "Request"], [0, 1, 1, "", "Response"]], "flask.wrappers.Request": [[0, 7, 1, "", "blueprint"], [0, 7, 1, "", "blueprints"], [0, 7, 1, "", "endpoint"], [0, 3, 1, "", "json_module"], [0, 7, 1, "", "max_content_length"], [0, 7, 1, "", "max_form_memory_size"], [0, 7, 1, "", "max_form_parts"], [0, 2, 1, "", "on_json_loading_failed"], [0, 3, 1, "", "routing_exception"], [0, 3, 1, "", "url_rule"], [0, 3, 1, "", "view_args"]], "flask.wrappers.Response": [[0, 3, 1, "", "autocorrect_location_header"], [0, 3, 1, "", "default_mimetype"], [0, 3, 1, "", "json_module"], [0, 7, 1, "", "max_cookie_size"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "class", "Python class"], "2": ["py", "method", "Python method"], "3": ["py", "attribute", "Python attribute"], "4": ["py", "exception", "Python exception"], "5": ["py", "function", "Python function"], "6": ["py", "data", "Python data"], "7": ["py", "property", "Python property"]}, "objtypes": {"0": "py:module", "1": "py:class", "2": "py:method", "3": "py:attribute", "4": "py:exception", "5": "py:function", "6": "py:data", "7": "py:property"}, "terms": {"": [0, 1], "0": [0, 1], "1": [0, 1], "10": 0, "1000": 0, "11": [0, 1], "12": 0, "127": 0, "1_000": 0, "2": [0, 1], "2231": 0, "3": [0, 1], "302": 0, "307": 0, "308": 0, "31": 0, "4": 0, "400": 0, "404": 0, "4093": 0, "413": 0, "415": 0, "42": 0, "5": 0, "500": 0, "5000": 0, "500000": 0, "500_000": 0, "6": 0, "7": 0, "8": [0, 1], "822": 1, "9": 0, "A": [0, 1], "As": 0, "By": 0, "For": 0, "If": [0, 1], "In": [0, 1], "It": [0, 1], "No": 0, "Not": 0, "On": 0, "Or": 0, "The": [0, 1], "Then": 0, "There": 0, "To": [0, 1], "Will": [0, 1], "_": 0, "__": [0, 1], "__call__": 0, "__html__": 1, "__init__": 0, "__name__": 0, "__slots__": 1, "_anchor": 0, "_app": 1, "_authent": 0, "_cider": 0, "_extern": 0, "_method": 0, "_perman": 0, "_scheme": 0, "abil": 0, "abl": 0, "abort": [0, 3], "absolut": 0, "accept": 0, "access": [0, 3], "accord": 0, "across": 0, "act": 0, "action": 0, "activ": [0, 1], "actual": 0, "ad": [0, 1], "adapt": 0, "add": [0, 1], "add_default_command": 0, "add_etag": 0, "add_head": 0, "add_url_rul": 0, "add_version_opt": 0, "addit": [0, 1], "addition": 0, "adhoc": 0, "advanc": 0, "advantag": 0, "after": 0, "after_request": 0, "after_this_request": [0, 3], "against": 0, "aid": 0, "alia": 0, "all": [0, 1], "allow": [0, 1], "allow_dash": 0, "alreadi": [0, 1], "also": [0, 1], "altern": 0, "alwai": [0, 1], "an": [0, 1], "anchor": 0, "ancient": 1, "ani": [0, 1], "answer": 0, "anystr": 0, "anyth": [0, 1], "api": [0, 1], "app": [1, 3], "app_context": [0, 3], "app_import_path": [0, 3], "app_nam": 0, "appcontext": [0, 3], "appcontext_tearing_down": 0, "appear": 0, "append": [0, 1], "appgroup": [0, 3], "appli": [0, 1], "applic": [0, 1, 3], "application_root": 0, "appropri": 0, "ar": [0, 1], "arbitrari": 0, "arg": [0, 1], "argument": [0, 1], "around": [0, 1], "arrai": 1, "arriv": 0, "as_attach": 0, "as_tupl": 0, "as_view": [0, 3], "ascii": [0, 1], "asctim": 0, "asdict": 1, "ask": 0, "assert": 0, "assertionerror": 0, "assign": 0, "associ": 0, "assum": 0, "assumpt": 0, "async": 0, "async_to_sync": [0, 3], "attach": 0, "attachment_filenam": 0, "attempt": 0, "attr": 0, "attribut": [0, 1], "authent": 0, "auto": 0, "auto_reload": 0, "autocorrect_location_head": [0, 3], "automat": [0, 1], "avail": [0, 1], "avoid": 0, "await": 0, "b": [0, 1], "back": [0, 1], "backend": 0, "bad": 0, "badli": 0, "badrequest": 0, "base": [0, 1], "base_url": 0, "baseexcept": 0, "baseload": 0, "basic": 0, "becaus": 0, "becom": 0, "been": 0, "befor": [0, 1], "before_request": 0, "before_request_func": 0, "begin": 0, "behav": 0, "behavior": [0, 1], "being": 0, "belong": 0, "below": 0, "best": 0, "better": [0, 1], "bienvenido": 2, "bigger": 0, "binari": [0, 1], "binaryio": 0, "bind": [0, 1], "block": 0, "blueprint": 3, "bodi": 0, "bool": [0, 1], "boolean": 0, "both": [0, 1], "bottom": 0, "bound": 0, "broader": 0, "browser": [0, 1], "buffer": 0, "build": 0, "builderror": 0, "built": [0, 1], "byte": [0, 1], "bytesio": 0, "c": 0, "cabc": 0, "cach": [0, 1], "cache_timeout": 0, "calcul": 0, "call": [0, 1], "callabl": 0, "callback": 0, "callbackdict": 0, "can": [0, 1], "cannot": 0, "care": 0, "case": [0, 1], "catch": 0, "categori": 0, "category_filt": 0, "caus": 0, "central": 0, "cert": 0, "certain": 0, "certparamtyp": [0, 3], "cfg": 0, "chain": 0, "chang": [0, 1], "chapter": 0, "charact": 1, "check": [0, 1], "class": [0, 1], "class_arg": 0, "class_kwarg": 0, "classmethod": 0, "classvar": 0, "cleanup": 0, "clear": [0, 3], "cli": 3, "cli_group": 0, "click": 0, "client": [0, 1], "clirunn": 0, "close": 0, "closur": 0, "code": 0, "coerc": 0, "collect": 0, "com": 0, "combin": 0, "come": 0, "command": [0, 3], "common": 0, "commonli": 0, "compact": [0, 1], "compactli": 1, "compat": [0, 1], "complain": 0, "complex": 0, "concurr": 0, "condit": 0, "config": 3, "configattribut": [0, 3], "configur": [0, 1], "confus": 0, "conn": 0, "connect": 0, "consid": 0, "consist": 0, "constructor": 0, "contain": 0, "content": 3, "content_typ": 0, "context": [0, 1], "context_class": 0, "continu": 0, "control": [0, 1], "convert": [0, 1, 3], "cooki": 0, "cool": 0, "copi": [0, 3], "copy_current_request_context": [0, 3], "coroutin": 0, "correct": [0, 1], "correspond": 0, "could": 0, "counter": 0, "counterapi": 0, "craft": 0, "creat": [0, 1], "create_app": [0, 3], "create_jinja_environ": [0, 3], "create_logg": [0, 3], "create_url_adapt": [0, 3], "ctx": 3, "current": [0, 1], "current_app": [0, 1], "custom": [0, 1], "customcli": 0, "d": [0, 1], "dai": 0, "data": [0, 1, 3], "databas": 0, "dataclass": 1, "date": [0, 1], "datetim": [0, 1], "db": 0, "deal": 0, "debug": [0, 1], "debugfileskeyerror": [0, 3], "debugg": 0, "debughelp": 3, "decid": 0, "decim": 1, "decis": 0, "decor": [0, 3], "def": [0, 1], "default": [0, 1], "default_config": [0, 3], "default_handl": [0, 3], "default_mimetyp": [0, 3], "default_tag": [0, 1], "defaultjsonprovid": [0, 1], "defer": 0, "defin": [0, 1], "del": 2, "delai": 0, "delet": 0, "depend": 0, "deploi": 0, "deriv": 0, "descript": 0, "deseri": 1, "detail": 0, "detect": 0, "determin": 0, "dev": 0, "develop": 0, "di": 1, "dict": [0, 1], "dictionari": 0, "did": 0, "didn": 0, "differ": [0, 1], "digest_method": [0, 3], "dir_okai": 0, "direct_passthrough": 0, "directli": [0, 1], "directori": 0, "disabl": [0, 1], "disappear": 0, "discov": 0, "dispatch": 0, "dispatch_request": [0, 3], "dispatchingjinjaload": [0, 3], "displai": 0, "disposit": 0, "distinct": 0, "do": 0, "do_some_work": 0, "do_teardown_appcontext": [0, 3], "do_teardown_request": [0, 3], "doc": 0, "document": 0, "doe": [0, 1], "doesn": 0, "domain": 0, "don": [0, 1], "done": 0, "dotenv": 0, "doubl": 0, "down": 0, "download_fil": 0, "download_nam": 0, "downsid": 0, "drop": 0, "due": 0, "dump": [0, 1], "duplic": 0, "dure": [0, 1], "e": 0, "each": 0, "easier": [0, 1], "edgar": 0, "effect": 0, "effici": 0, "either": [0, 1], "els": 0, "elsewher": 0, "email": 0, "empti": [0, 1], "enabl": [0, 1], "encod": [0, 1], "encount": 0, "end": [0, 1], "endmacro": 0, "endpoint": [0, 3], "enforc": 0, "ensur": 0, "ensure_ascii": [0, 1], "ensure_sync": [0, 3], "env": 0, "environ": [0, 3], "environ_bas": 0, "environbuild": [0, 3], "equival": 0, "error": 0, "escap": 1, "especi": 0, "etag": 0, "etc": 0, "evalu": 0, "even": 0, "event": 0, "everi": 0, "everyth": 0, "exact": 0, "exactli": 0, "exampl": [0, 1], "exc": 0, "exc_info": 0, "exceed": 0, "except": 0, "execut": 0, "executescript": 0, "exist": [0, 1], "exit": 0, "expand": 0, "expect": 0, "experi": 0, "expir": 0, "explain_template_load": 0, "explain_template_loading_attempt": [0, 3], "explicitli": 0, "export": 0, "extend": [0, 1], "extens": 0, "extern": 0, "extra": [0, 1], "f": 0, "fail": 0, "failur": 0, "fall": 0, "fals": [0, 1], "few": 0, "field": 0, "file": [0, 1], "file_okai": 0, "file_wrapp": 0, "filenam": 0, "filename_or_fp": 0, "filesystem": 0, "filewrapp": 0, "fill": 0, "filter": 0, "final": 0, "finalize_request": [0, 3], "find": 0, "find_app_by_str": [0, 3], "find_best_app": [0, 3], "first": 1, "flag": 0, "flash": [0, 3], "flask_": 0, "flask_debug": 0, "flask_skip_dotenv": 0, "flaskclient": [0, 3], "flaskclirunn": [0, 3], "flaskenv": 0, "flaskgroup": [0, 3], "float": 0, "folder": 0, "follow": [0, 1], "follow_redirect": 0, "foo": 0, "forc": [0, 1], "form": 0, "format": [0, 1], "formdataroutingredirect": [0, 3], "forward": 0, "found": 0, "fp": 1, "from": [0, 1], "from_envvar": [0, 3], "from_error_handl": 0, "from_fil": [0, 3], "from_map": [0, 3], "from_object": [0, 3], "from_prefixed_env": [0, 3], "from_pyfil": [0, 3], "front": 1, "frontend": 0, "ft": 0, "fulfil": 0, "full": 0, "full_dispatch_request": [0, 3], "func": 0, "function": [0, 1], "further": 0, "futur": 0, "g": 0, "gener": 0, "generate_report": 0, "generator_or_funct": 0, "get": [0, 1, 3], "get_command": [0, 3], "get_convert": 0, "get_cookie_domain": [0, 3], "get_cookie_httponli": [0, 3], "get_cookie_nam": [0, 3], "get_cookie_partit": [0, 3], "get_cookie_path": [0, 3], "get_cookie_samesit": [0, 3], "get_cookie_secur": [0, 3], "get_debug_flag": [0, 3], "get_expiration_tim": [0, 3], "get_flashed_messag": [0, 3], "get_json": 0, "get_load_dotenv": [0, 3], "get_namespac": [0, 3], "get_send_file_max_ag": [0, 3], "get_signing_seri": [0, 3], "get_sourc": [0, 3], "get_template_attribut": [0, 3], "get_vers": [0, 3], "gevent": 0, "give": [0, 1], "given": [0, 1], "global": 3, "go": 0, "got_request_except": 0, "greenlet": 0, "group": [0, 3], "guarante": 0, "guess": 0, "guid": 0, "ha": 0, "handl": [0, 1], "handle_except": [0, 3], "handle_http_except": [0, 3], "handle_url_build_error": 0, "handle_user_except": [0, 3], "handler": 0, "happen": 0, "hard": 0, "hardcod": 0, "has_app_context": [0, 3], "has_level_handl": [0, 3], "has_request_context": [0, 3], "hash": 0, "have": [0, 1], "head": 0, "header": 0, "hello": 0, "help": 0, "helper": 3, "here": 0, "histori": 0, "hmac": 0, "home": 0, "hook": 0, "host": 0, "host_match": 0, "hostnam": 0, "hour": 0, "how": [0, 1], "howev": 0, "html": 0, "http": [0, 1], "httpexcept": 0, "httponli": 0, "httpstatu": 0, "i": [0, 1], "idea": 0, "ideal": 0, "identifi": 1, "ignor": 0, "imag": 0, "image_store_": 0, "image_store_base_url": 0, "image_store_config": 0, "image_store_path": 0, "image_store_typ": 0, "img": 0, "immedi": 0, "implement": [0, 1], "implicitli": 0, "import": [0, 1], "import_nam": 0, "improv": 0, "includ": 0, "incorrect": 0, "indent": [0, 1], "index": [0, 1], "indic": 0, "infer": 0, "infinit": 0, "info": 0, "info_nam": 0, "inform": 0, "inherit": 0, "init": 0, "init_db": 0, "init_every_request": [0, 3], "initi": 0, "inject": 0, "inlin": 0, "input": 0, "insecur": 0, "insert": [0, 1], "insid": 0, "inspect": 0, "instal": 0, "instanc": [0, 1], "instance_path": 0, "instance_relative_config": 0, "instanti": [0, 1], "instead": 0, "int": [0, 1], "integ": 0, "intend": 0, "interact": 0, "interest": 0, "interfac": 0, "intermedi": [0, 1], "intern": [0, 1], "internalservererror": 0, "interpret": 0, "invalid": 0, "invoc": 0, "invok": [0, 3], "io": [0, 1], "is_null_sess": [0, 3], "isinst": 1, "isn": 0, "isol": 0, "item": [0, 1], "iter": 0, "iteritem": 1, "its": [0, 1], "itsdanger": [0, 1], "itself": 0, "jinja": 0, "jinja2": 0, "jinja_opt": 0, "job": 0, "json": [0, 3], "json_dump": [0, 3], "json_modul": [0, 3], "json_provider_class": 1, "jsonifi": [0, 1], "jsonprovid": [0, 1], "jsontag": [0, 1], "just": 0, "k": [0, 1], "kei": [0, 1], "key_deriv": [0, 3], "keyerror": [0, 1], "keyword": [0, 1], "kick": 0, "kind": 0, "know": [0, 1], "knowledg": 0, "kwarg": [0, 1], "la": 2, "lack": 0, "last": 0, "last_modifi": 0, "later": 1, "latin": 0, "launch": 0, "lax": 0, "leak": 0, "least": [0, 1], "left": 0, "length": 0, "less": 0, "let": 1, "level": [0, 1], "levelnam": 0, "librari": 1, "lifetim": 0, "lifo": 0, "like": 0, "likewis": 0, "limit": 0, "line": 0, "link": 0, "linux": 0, "list": [0, 1], "list_command": [0, 3], "list_templ": [0, 3], "listen": 0, "liter": 0, "load": [0, 1], "load_app": [0, 3], "load_default": 0, "load_dotenv": [0, 3], "load_dotenv_default": [0, 3], "loader": 0, "local": 0, "locat": 0, "locate_app": [0, 3], "lock": 0, "log": 3, "log_except": [0, 3], "logger": 0, "long": 0, "longer": 0, "look": 0, "lookup": 0, "lose": 0, "lossless": 1, "lost": 0, "lot": 0, "lowercas": 0, "m": 1, "macro": 0, "made": 0, "mai": [0, 1], "main": [0, 3], "mainli": 0, "maintain": 0, "make": [0, 1], "make_context": [0, 3], "make_default_options_respons": [0, 3], "make_null_sess": [0, 3], "make_respons": [0, 3], "make_shell_context": [0, 3], "malici": 0, "manag": 0, "manual": 0, "map": 0, "mapadapt": 0, "mark": 1, "markup": 1, "match": [0, 1], "match_request": [0, 3], "max_ag": 0, "max_content_length": [0, 3], "max_cookie_s": [0, 3], "max_form_memory_s": [0, 3], "max_form_part": [0, 3], "maximum": 0, "mean": 0, "meet": 0, "memori": 0, "messag": 0, "method": [0, 1, 3], "methodnotallow": 0, "methodview": [0, 3], "middlewar": 0, "might": 0, "mime": 0, "mimetyp": [0, 1], "miss": 0, "mixin": 0, "mode": [0, 1], "model": 0, "modif": 0, "modifi": [0, 3], "modul": 3, "module_nam": 0, "moduletyp": 0, "moment": 0, "more": [0, 1], "most": 0, "mostli": 0, "move": 0, "mro": 0, "much": 0, "multipart": 0, "multipl": [0, 1], "must": [0, 1], "mutabl": 0, "mutablemap": 0, "mymiddlewar": 0, "mysessioninterfac": 0, "name": [0, 3], "namespac": 0, "nearest": 0, "necessari": [0, 1], "necessarili": 0, "need": [0, 1], "nest": 0, "never": 0, "new": [0, 1, 3], "newlin": 1, "next": 0, "nicer": 0, "noappexcept": [0, 3], "non": [0, 1], "none": [0, 1], "noreturn": 0, "normal": 0, "not_found": 0, "note": 0, "notfound": 0, "noth": 0, "notset": 0, "now": 0, "null": 0, "null_session_class": [0, 3], "nullsess": [0, 3], "number": 0, "o": [0, 1], "obj": [0, 1], "object": [0, 1], "occur": 0, "od": 1, "off": 0, "offer": 0, "often": 0, "old": 0, "on_json_loading_fail": [0, 3], "onc": 0, "one": 0, "ones": 0, "onli": [0, 1], "onward": 0, "op": 0, "open": [0, 1, 3], "open_instance_resourc": [0, 3], "open_resourc": [0, 3], "open_sess": [0, 3], "oper": 1, "option": 0, "order": [0, 1], "ordereddict": 1, "origin": [0, 1], "original_except": 0, "other": [0, 1], "otherwis": [0, 1], "out": [0, 1], "outlin": 0, "output": 1, "outsid": 0, "over": 0, "overrid": [0, 1], "overridden": 0, "overwrit": [0, 1], "own": 0, "packag": [2, 3], "page": 0, "pain": 0, "pair": [0, 1], "parachut": 0, "param": 0, "paramet": 1, "paramtyp": 0, "parent": 0, "pars": 0, "parse_arg": [0, 3], "parser": 0, "part": 0, "partit": 0, "pass": [0, 1], "passdict": [0, 1], "passlist": [0, 1], "path": 0, "path_or_fil": 0, "path_typ": 0, "pathlik": 0, "pattern": 0, "payload": 0, "per": 0, "perform": [0, 1], "perman": [0, 3], "permanent_session_lifetim": 0, "pick": 0, "pickl": 0, "pickle_bas": [0, 3], "place": [0, 1], "plai": 0, "plain": 0, "plu": 0, "point": 0, "pointer": 0, "pop": [0, 3], "popitem": [0, 3], "popul": 0, "populate_request": 0, "port": 0, "posit": [0, 1], "possibl": 0, "post": 0, "postprocess": 0, "pre": 0, "preced": 0, "prefer": 0, "preferred_url_schem": 0, "prefix": 0, "prepare_import": [0, 3], "prepend": 0, "preprocess_request": [0, 3], "present": 0, "preserv": 0, "preset": 0, "prevent": 0, "previous": 0, "probabl": 0, "process": [0, 1], "process_respons": [0, 3], "processor": 0, "prod": 0, "product": 0, "prompt": 0, "propag": 0, "propagate_except": 0, "proper": 0, "properli": 0, "properti": 0, "provid": [0, 3], "provide_automatic_opt": [0, 3], "proxi": [0, 1], "proyecto": 2, "public": 0, "pull": 0, "push": [0, 3], "py": 0, "python": [0, 1], "queri": 0, "quickli": 0, "quit": 0, "r": 0, "rais": [0, 1], "raise_if_not_found": 0, "rang": 0, "rather": [0, 1], "rb": 0, "re": 0, "read": [0, 1], "readabl": 0, "reader": 0, "real": 0, "reason": 0, "receiv": 0, "recommend": 0, "reconstruct": 0, "redirect": [0, 3], "refer": 0, "referenc": 0, "reflect": 0, "regard": 0, "regist": [0, 1], "registr": 0, "registri": 0, "regular": 0, "rel": 0, "relat": 0, "reliabl": 0, "reload": 0, "remain": 0, "rememb": 0, "remote_addr": 0, "remov": [0, 1], "render": 0, "render_templ": [0, 3], "render_template_str": [0, 3], "replac": [0, 1], "repo": 0, "report": 0, "repres": [0, 1], "represent": 1, "reqcontext": 0, "request": [0, 1, 3], "request_class": [0, 3], "request_context": [0, 3], "request_tearing_down": 0, "requestcontext": [0, 3], "requestentitytoolarg": 0, "requir": [0, 1], "rerais": 0, "resolv": 0, "resolve_path": 0, "resourc": 0, "respons": [0, 1, 3], "response_class": [0, 3], "responsereturnvalu": 0, "rest": 0, "restor": 0, "restrict": 0, "result": [0, 1], "retain": 0, "return": [0, 1], "revers": 0, "rfc": [0, 1], "right": 0, "risk": 1, "role": 0, "root": 0, "root_path": 0, "rout": 0, "routecal": 0, "routing_except": [0, 3], "routingexcept": 0, "rt": 0, "rule": 0, "run": [0, 3], "run_simpl": 0, "runner": 0, "rv": 0, "safe": 0, "safe_join": 0, "salt": [0, 3], "same": [0, 1], "samesit": 0, "save": 0, "save_sess": [0, 3], "scaffold": 0, "schema": 0, "scheme": 0, "screen": 0, "script": 0, "scriptinfo": [0, 3], "search": 0, "second": 0, "secret": 0, "secret_kei": 0, "secret_key_fallback": 0, "secur": [0, 1], "securecooki": 0, "securecookiesess": [0, 3], "securecookiesessioninterfac": [0, 1, 3], "see": [0, 1], "seek": 0, "self": [0, 1], "send": 0, "send_fil": [0, 3], "send_file_max_age_default": 0, "send_from_directori": [0, 3], "send_static_fil": [0, 3], "sendfil": 0, "sens": 0, "sent": 0, "separ": 0, "separatedpathtyp": [0, 3], "sequenc": [0, 1], "serial": [0, 1, 3], "serv": 0, "server": 0, "server_nam": 0, "session": [1, 3], "session_class": [0, 3], "session_cookie_domain": 0, "session_cookie_httponli": 0, "session_cookie_nam": 0, "session_cookie_partit": 0, "session_cookie_path": 0, "session_cookie_samesit": 0, "session_cookie_secur": 0, "session_interfac": [0, 1, 3], "session_refresh_each_request": 0, "session_transact": [0, 3], "sessioninterfac": [0, 3], "sessionmixin": [0, 3], "set": [0, 1], "set_debug_flag": 0, "setdefault": [0, 3], "setup": 0, "sha1": 0, "shallow": 0, "shell": 0, "shortcut": 0, "should": [0, 1], "should_set_cooki": [0, 3], "show": 0, "show_server_bann": [0, 3], "sign": 0, "signal": 3, "signatur": 0, "silenc": 0, "silent": 0, "similar": 0, "similarli": 0, "sinc": [0, 1], "singl": [0, 1], "situat": [0, 1], "size": [0, 1], "skip": 0, "slash": 0, "so": [0, 1], "software_d": 0, "some": [0, 1], "someth": 0, "sometim": 0, "somewher": 0, "sort": [0, 1], "sort_kei": [0, 1], "sourc": 0, "space": 1, "spawn": 0, "special": [0, 1], "specif": [0, 1], "specifi": 0, "split": 0, "sql": 0, "sqlalchemi": 0, "src": 0, "sslcontext": 0, "standard": [0, 1], "start": 0, "start_respons": 0, "startrespons": 0, "startup": 0, "state": 0, "statement": 0, "static": [0, 1], "static_fold": 0, "static_host": 0, "static_url_path": 0, "statu": 0, "stderr": 0, "step": 1, "still": 0, "stop": 0, "store": [0, 1], "str": [0, 1], "stream": 0, "stream_templ": [0, 3], "stream_template_str": [0, 3], "stream_with_context": [0, 3], "streamed_respons": 0, "streamhandl": 0, "strict": 0, "string": [0, 1], "structur": 1, "subclass": [0, 1], "subcommand": 0, "subdomain": 0, "subdomain_match": 0, "submodul": 3, "subpackag": 3, "subset": 0, "successfulli": 0, "suffix": 1, "super": 0, "support": [0, 1], "suppress": 0, "sure": 0, "sync": 0, "synchron": 0, "syntax": 0, "system": [0, 1], "t": [0, 1], "tag": [0, 3], "tag_class": 1, "tagbyt": [0, 1], "tagdatetim": [0, 1], "tagdict": [0, 1], "taggedjsonseri": [0, 1], "tagmarkup": [0, 1], "tagordereddict": 1, "tagtupl": [0, 1], "taguuid": [0, 1], "take": 0, "teardown": 0, "teardown_appcontext": 0, "teardown_request": 0, "tell": 0, "templat": 3, "template_fold": 0, "template_nam": 0, "template_name_or_list": 0, "templatenotfound": 0, "templates_auto_reload": 0, "temporari": 0, "termin": 0, "test": 3, "test_cli_runn": [0, 3], "test_cli_runner_class": 0, "test_client": [0, 3], "test_client_class": 0, "test_request_context": [0, 3], "testrespons": 0, "text": [0, 1], "textiobas": 0, "than": [0, 1], "thank": 0, "thei": [0, 1], "them": 0, "thi": [0, 1], "thing": 0, "think": 0, "those": 0, "though": 0, "thread": 0, "through": 0, "time": 0, "timedelta": 0, "to_json": [0, 1], "to_python": [0, 1], "toml": 0, "tomllib": 0, "top": [0, 1], "toplevel": 0, "traceback": 0, "tracebacktyp": 0, "track": 0, "transact": 0, "trap_bad_request_error": 0, "trap_http_except": 0, "treat": 1, "tri": 0, "tricki": 0, "trigger": 0, "trim_namespac": 0, "true": [0, 1], "trust": 0, "trusted_host": 0, "truth": 0, "try": 0, "tupl": [0, 1], "two": 0, "type": [1, 3], "typecheck": 0, "typeerror": [0, 1], "typic": 0, "u": 1, "ucr": 0, "unavail": 0, "unbind": 0, "unchang": 0, "under": 0, "underli": [0, 1], "underscor": 0, "understand": 0, "unexpect": 0, "unexpectedunicodeerror": [0, 3], "unhandl": 0, "unicod": 0, "unicodeerror": 0, "unit": 0, "unknown": 0, "unless": 0, "unlik": 0, "unreli": 0, "untag": [0, 1], "until": 0, "up": 0, "updat": [0, 3], "update_template_context": [0, 3], "upload": 0, "upload_fold": 0, "upper": 0, "uppercas": 0, "uptod": 0, "upward": 0, "url": 0, "url_default": 0, "url_for": [0, 3], "url_map": 0, "url_prefix": 0, "url_rul": [0, 3], "url_schem": 0, "url_value_preprocessor": 0, "urlsafetimedseri": 0, "us": [0, 1], "usag": 0, "usageerror": 0, "use_cooki": 0, "use_debugg": 0, "use_evalex": 0, "use_reload": 0, "use_x_sendfil": 0, "user": 0, "usernam": 0, "usual": 0, "utf": [0, 1], "util": 0, "uuid": 1, "v": [0, 1], "valid": [0, 1], "valid_method": 0, "valu": [0, 1], "valueerror": 0, "var": 0, "variabl": 0, "variable_nam": 0, "variou": 0, "veri": 0, "version": [0, 1], "via": 0, "view": [1, 3], "view_arg": [0, 3], "view_func": 0, "view_funct": 0, "view_rv": 0, "visibl": 0, "vodka": 0, "wa": [0, 1], "wai": 0, "wait": 0, "want": 0, "warn": 0, "wasn": 0, "we": [0, 1], "weakref": 1, "web": 0, "webserv": 0, "websit": 0, "well": 0, "were": 0, "werkzeug": 0, "what": 0, "when": [0, 1], "whenev": 0, "where": 0, "whether": 0, "which": 0, "while": 0, "whose": 1, "why": 0, "wide": 0, "window": 0, "with_appcontext": [0, 3], "with_categori": 0, "within": 0, "without": [0, 1], "won": 0, "work": 0, "worker": 0, "world": 0, "would": 0, "wrap": 0, "wrapper": 3, "writabl": 0, "write": [0, 1], "written": 0, "wsgi": 0, "wsgi_app": [0, 3], "wsgi_errors_stream": 0, "wsgienviron": 0, "x": 0, "yet": 0, "yield": 0, "you": 0, "your": 0, "yourappl": 0, "yourapplication_set": 0, "yourconfig": 0, "yourself": 0}, "titles": ["flask package", "flask.json package", "Flask - Documentaci\u00f3n Personalizada", "flask"], "titleterms": {"about": 0, "app": 0, "blueprint": 0, "cli": 0, "config": 0, "contenido": 2, "content": [0, 1], "ctx": 0, "debughelp": 0, "documentaci\u00f3n": 2, "first": 0, "flask": [0, 1, 2, 3], "global": 0, "helper": 0, "json": 1, "keep": 0, "log": 0, "mind": 0, "modul": [0, 1], "packag": [0, 1], "paramet": 0, "personalizada": 2, "provid": 1, "session": 0, "signal": 0, "submodul": [0, 1], "subpackag": 0, "tag": 1, "templat": 0, "test": 0, "type": 0, "view": 0, "wrapper": 0}})
\ No newline at end of file
diff --git a/docs/changes.rst b/docs/changes.rst
deleted file mode 100644
index 955deaf2..00000000
--- a/docs/changes.rst
+++ /dev/null
@@ -1,4 +0,0 @@
-Changes
-=======
-
-.. include:: ../CHANGES.rst
diff --git a/docs/cli.rst b/docs/cli.rst
deleted file mode 100644
index a72e6d51..00000000
--- a/docs/cli.rst
+++ /dev/null
@@ -1,556 +0,0 @@
-.. currentmodule:: flask
-
-Command Line Interface
-======================
-
-Installing Flask installs the ``flask`` script, a `Click`_ command line
-interface, in your virtualenv. Executed from the terminal, this script gives
-access to built-in, extension, and application-defined commands. The ``--help``
-option will give more information about any commands and options.
-
-.. _Click: https://click.palletsprojects.com/
-
-
-Application Discovery
----------------------
-
-The ``flask`` command is installed by Flask, not your application; it must be
-told where to find your application in order to use it. The ``--app``
-option is used to specify how to load the application.
-
-While ``--app`` supports a variety of options for specifying your
-application, most use cases should be simple. Here are the typical values:
-
-(nothing)
- The name "app" or "wsgi" is imported (as a ".py" file, or package),
- automatically detecting an app (``app`` or ``application``) or
- factory (``create_app`` or ``make_app``).
-
-``--app hello``
- The given name is imported, automatically detecting an app (``app``
- or ``application``) or factory (``create_app`` or ``make_app``).
-
-----
-
-``--app`` has three parts: an optional path that sets the current working
-directory, a Python file or dotted import path, and an optional variable
-name of the instance or factory. If the name is a factory, it can optionally
-be followed by arguments in parentheses. The following values demonstrate these
-parts:
-
-``--app src/hello``
- Sets the current working directory to ``src`` then imports ``hello``.
-
-``--app hello.web``
- Imports the path ``hello.web``.
-
-``--app hello:app2``
- Uses the ``app2`` Flask instance in ``hello``.
-
-``--app 'hello:create_app("dev")'``
- The ``create_app`` factory in ``hello`` is called with the string ``'dev'``
- as the argument.
-
-If ``--app`` is not set, the command will try to import "app" or
-"wsgi" (as a ".py" file, or package) and try to detect an application
-instance or factory.
-
-Within the given import, the command looks for an application instance named
-``app`` or ``application``, then any application instance. If no instance is
-found, the command looks for a factory function named ``create_app`` or
-``make_app`` that returns an instance.
-
-If parentheses follow the factory name, their contents are parsed as
-Python literals and passed as arguments and keyword arguments to the
-function. This means that strings must still be in quotes.
-
-
-Run the Development Server
---------------------------
-
-The :func:`run ` command will start the development server. It
-replaces the :meth:`Flask.run` method in most cases. ::
-
- $ flask --app hello run
- * Serving Flask app "hello"
- * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
-
-.. warning:: Do not use this command to run your application in production.
- Only use the development server during development. The development server
- is provided for convenience, but is not designed to be particularly secure,
- stable, or efficient. See :doc:`/deploying/index` for how to run in production.
-
-If another program is already using port 5000, you'll see
-``OSError: [Errno 98]`` or ``OSError: [WinError 10013]`` when the
-server tries to start. See :ref:`address-already-in-use` for how to
-handle that.
-
-
-Debug Mode
-~~~~~~~~~~
-
-In debug mode, the ``flask run`` command will enable the interactive debugger and the
-reloader by default, and make errors easier to see and debug. To enable debug mode, use
-the ``--debug`` option.
-
-.. code-block:: console
-
- $ flask --app hello run --debug
- * Serving Flask app "hello"
- * Debug mode: on
- * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
- * Restarting with inotify reloader
- * Debugger is active!
- * Debugger PIN: 223-456-919
-
-The ``--debug`` option can also be passed to the top level ``flask`` command to enable
-debug mode for any command. The following two ``run`` calls are equivalent.
-
-.. code-block:: console
-
- $ flask --app hello --debug run
- $ flask --app hello run --debug
-
-
-Watch and Ignore Files with the Reloader
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-When using debug mode, the reloader will trigger whenever your Python code or imported
-modules change. The reloader can watch additional files with the ``--extra-files``
-option. Multiple paths are separated with ``:``, or ``;`` on Windows.
-
-.. code-block:: text
-
- $ flask run --extra-files file1:dirA/file2:dirB/
- * Running on http://127.0.0.1:8000/
- * Detected change in '/path/to/file1', reloading
-
-The reloader can also ignore files using :mod:`fnmatch` patterns with the
-``--exclude-patterns`` option. Multiple patterns are separated with ``:``, or ``;`` on
-Windows.
-
-
-Open a Shell
-------------
-
-To explore the data in your application, you can start an interactive Python
-shell with the :func:`shell ` command. An application
-context will be active, and the app instance will be imported. ::
-
- $ flask shell
- Python 3.10.0 (default, Oct 27 2021, 06:59:51) [GCC 11.1.0] on linux
- App: example [production]
- Instance: /home/david/Projects/pallets/flask/instance
- >>>
-
-Use :meth:`~Flask.shell_context_processor` to add other automatic imports.
-
-
-.. _dotenv:
-
-Environment Variables From dotenv
----------------------------------
-
-The ``flask`` command supports setting any option for any command with
-environment variables. The variables are named like ``FLASK_OPTION`` or
-``FLASK_COMMAND_OPTION``, for example ``FLASK_APP`` or
-``FLASK_RUN_PORT``.
-
-Rather than passing options every time you run a command, or environment
-variables every time you open a new terminal, you can use Flask's dotenv
-support to set environment variables automatically.
-
-If `python-dotenv`_ is installed, running the ``flask`` command will set
-environment variables defined in the files ``.env`` and ``.flaskenv``.
-You can also specify an extra file to load with the ``--env-file``
-option. Dotenv files can be used to avoid having to set ``--app`` or
-``FLASK_APP`` manually, and to set configuration using environment
-variables similar to how some deployment services work.
-
-Variables set on the command line are used over those set in :file:`.env`,
-which are used over those set in :file:`.flaskenv`. :file:`.flaskenv` should be
-used for public variables, such as ``FLASK_APP``, while :file:`.env` should not
-be committed to your repository so that it can set private variables.
-
-Directories are scanned upwards from the directory you call ``flask``
-from to locate the files.
-
-The files are only loaded by the ``flask`` command or calling
-:meth:`~Flask.run`. If you would like to load these files when running in
-production, you should call :func:`~cli.load_dotenv` manually.
-
-.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
-
-
-Setting Command Options
-~~~~~~~~~~~~~~~~~~~~~~~
-
-Click is configured to load default values for command options from
-environment variables. The variables use the pattern
-``FLASK_COMMAND_OPTION``. For example, to set the port for the run
-command, instead of ``flask run --port 8000``:
-
-.. tabs::
-
- .. group-tab:: Bash
-
- .. code-block:: text
-
- $ export FLASK_RUN_PORT=8000
- $ flask run
- * Running on http://127.0.0.1:8000/
-
- .. group-tab:: Fish
-
- .. code-block:: text
-
- $ set -x FLASK_RUN_PORT 8000
- $ flask run
- * Running on http://127.0.0.1:8000/
-
- .. group-tab:: CMD
-
- .. code-block:: text
-
- > set FLASK_RUN_PORT=8000
- > flask run
- * Running on http://127.0.0.1:8000/
-
- .. group-tab:: Powershell
-
- .. code-block:: text
-
- > $env:FLASK_RUN_PORT = 8000
- > flask run
- * Running on http://127.0.0.1:8000/
-
-These can be added to the ``.flaskenv`` file just like ``FLASK_APP`` to
-control default command options.
-
-
-Disable dotenv
-~~~~~~~~~~~~~~
-
-The ``flask`` command will show a message if it detects dotenv files but
-python-dotenv is not installed.
-
-.. code-block:: bash
-
- $ flask run
- * Tip: There are .env files present. Do "pip install python-dotenv" to use them.
-
-You can tell Flask not to load dotenv files even when python-dotenv is
-installed by setting the ``FLASK_SKIP_DOTENV`` environment variable.
-This can be useful if you want to load them manually, or if you're using
-a project runner that loads them already. Keep in mind that the
-environment variables must be set before the app loads or it won't
-configure as expected.
-
-.. tabs::
-
- .. group-tab:: Bash
-
- .. code-block:: text
-
- $ export FLASK_SKIP_DOTENV=1
- $ flask run
-
- .. group-tab:: Fish
-
- .. code-block:: text
-
- $ set -x FLASK_SKIP_DOTENV 1
- $ flask run
-
- .. group-tab:: CMD
-
- .. code-block:: text
-
- > set FLASK_SKIP_DOTENV=1
- > flask run
-
- .. group-tab:: Powershell
-
- .. code-block:: text
-
- > $env:FLASK_SKIP_DOTENV = 1
- > flask run
-
-
-Environment Variables From virtualenv
--------------------------------------
-
-If you do not want to install dotenv support, you can still set environment
-variables by adding them to the end of the virtualenv's :file:`activate`
-script. Activating the virtualenv will set the variables.
-
-.. tabs::
-
- .. group-tab:: Bash
-
- Unix Bash, :file:`.venv/bin/activate`::
-
- $ export FLASK_APP=hello
-
- .. group-tab:: Fish
-
- Fish, :file:`.venv/bin/activate.fish`::
-
- $ set -x FLASK_APP hello
-
- .. group-tab:: CMD
-
- Windows CMD, :file:`.venv\\Scripts\\activate.bat`::
-
- > set FLASK_APP=hello
-
- .. group-tab:: Powershell
-
- Windows Powershell, :file:`.venv\\Scripts\\activate.ps1`::
-
- > $env:FLASK_APP = "hello"
-
-It is preferred to use dotenv support over this, since :file:`.flaskenv` can be
-committed to the repository so that it works automatically wherever the project
-is checked out.
-
-
-Custom Commands
----------------
-
-The ``flask`` command is implemented using `Click`_. See that project's
-documentation for full information about writing commands.
-
-This example adds the command ``create-user`` that takes the argument
-``name``. ::
-
- import click
- from flask import Flask
-
- app = Flask(__name__)
-
- @app.cli.command("create-user")
- @click.argument("name")
- def create_user(name):
- ...
-
-::
-
- $ flask create-user admin
-
-This example adds the same command, but as ``user create``, a command in a
-group. This is useful if you want to organize multiple related commands. ::
-
- import click
- from flask import Flask
- from flask.cli import AppGroup
-
- app = Flask(__name__)
- user_cli = AppGroup('user')
-
- @user_cli.command('create')
- @click.argument('name')
- def create_user(name):
- ...
-
- app.cli.add_command(user_cli)
-
-::
-
- $ flask user create demo
-
-See :ref:`testing-cli` for an overview of how to test your custom
-commands.
-
-
-Registering Commands with Blueprints
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If your application uses blueprints, you can optionally register CLI
-commands directly onto them. When your blueprint is registered onto your
-application, the associated commands will be available to the ``flask``
-command. By default, those commands will be nested in a group matching
-the name of the blueprint.
-
-.. code-block:: python
-
- from flask import Blueprint
-
- bp = Blueprint('students', __name__)
-
- @bp.cli.command('create')
- @click.argument('name')
- def create(name):
- ...
-
- app.register_blueprint(bp)
-
-.. code-block:: text
-
- $ flask students create alice
-
-You can alter the group name by specifying the ``cli_group`` parameter
-when creating the :class:`Blueprint` object, or later with
-:meth:`app.register_blueprint(bp, cli_group='...') `.
-The following are equivalent:
-
-.. code-block:: python
-
- bp = Blueprint('students', __name__, cli_group='other')
- # or
- app.register_blueprint(bp, cli_group='other')
-
-.. code-block:: text
-
- $ flask other create alice
-
-Specifying ``cli_group=None`` will remove the nesting and merge the
-commands directly to the application's level:
-
-.. code-block:: python
-
- bp = Blueprint('students', __name__, cli_group=None)
- # or
- app.register_blueprint(bp, cli_group=None)
-
-.. code-block:: text
-
- $ flask create alice
-
-
-Application Context
-~~~~~~~~~~~~~~~~~~~
-
-Commands added using the Flask app's :attr:`~Flask.cli` or
-:class:`~flask.cli.FlaskGroup` :meth:`~cli.AppGroup.command` decorator
-will be executed with an application context pushed, so your custom
-commands and parameters have access to the app and its configuration. The
-:func:`~cli.with_appcontext` decorator can be used to get the same
-behavior, but is not needed in most cases.
-
-.. code-block:: python
-
- import click
- from flask.cli import with_appcontext
-
- @click.command()
- @with_appcontext
- def do_work():
- ...
-
- app.cli.add_command(do_work)
-
-
-Plugins
--------
-
-Flask will automatically load commands specified in the ``flask.commands``
-`entry point`_. This is useful for extensions that want to add commands when
-they are installed. Entry points are specified in :file:`pyproject.toml`:
-
-.. code-block:: toml
-
- [project.entry-points."flask.commands"]
- my-command = "my_extension.commands:cli"
-
-.. _entry point: https://packaging.python.org/tutorials/packaging-projects/#entry-points
-
-Inside :file:`my_extension/commands.py` you can then export a Click
-object::
-
- import click
-
- @click.command()
- def cli():
- ...
-
-Once that package is installed in the same virtualenv as your Flask project,
-you can run ``flask my-command`` to invoke the command.
-
-
-.. _custom-scripts:
-
-Custom Scripts
---------------
-
-When you are using the app factory pattern, it may be more convenient to define
-your own Click script. Instead of using ``--app`` and letting Flask load
-your application, you can create your own Click object and export it as a
-`console script`_ entry point.
-
-Create an instance of :class:`~cli.FlaskGroup` and pass it the factory::
-
- import click
- from flask import Flask
- from flask.cli import FlaskGroup
-
- def create_app():
- app = Flask('wiki')
- # other setup
- return app
-
- @click.group(cls=FlaskGroup, create_app=create_app)
- def cli():
- """Management script for the Wiki application."""
-
-Define the entry point in :file:`pyproject.toml`:
-
-.. code-block:: toml
-
- [project.scripts]
- wiki = "wiki:cli"
-
-Install the application in the virtualenv in editable mode and the custom
-script is available. Note that you don't need to set ``--app``. ::
-
- $ pip install -e .
- $ wiki run
-
-.. admonition:: Errors in Custom Scripts
-
- When using a custom script, if you introduce an error in your
- module-level code, the reloader will fail because it can no longer
- load the entry point.
-
- The ``flask`` command, being separate from your code, does not have
- this issue and is recommended in most cases.
-
-.. _console script: https://packaging.python.org/tutorials/packaging-projects/#console-scripts
-
-
-PyCharm Integration
--------------------
-
-PyCharm Professional provides a special Flask run configuration to run the development
-server. For the Community Edition, and for other commands besides ``run``, you need to
-create a custom run configuration. These instructions should be similar for any other
-IDE you use.
-
-In PyCharm, with your project open, click on *Run* from the menu bar and go to *Edit
-Configurations*. You'll see a screen similar to this:
-
-.. image:: _static/pycharm-run-config.png
- :align: center
- :class: screenshot
- :alt: Screenshot of PyCharm run configuration.
-
-Once you create a configuration for the ``flask run``, you can copy and change it to
-call any other command.
-
-Click the *+ (Add New Configuration)* button and select *Python*. Give the configuration
-a name such as "flask run".
-
-Click the *Script path* dropdown and change it to *Module name*, then input ``flask``.
-
-The *Parameters* field is set to the CLI command to execute along with any arguments.
-This example uses ``--app hello run --debug``, which will run the development server in
-debug mode. ``--app hello`` should be the import or file with your Flask app.
-
-If you installed your project as a package in your virtualenv, you may uncheck the
-*PYTHONPATH* options. This will more accurately match how you deploy later.
-
-Click *OK* to save and close the configuration. Select the configuration in the main
-PyCharm window and click the play button next to it to run the server.
-
-Now that you have a configuration for ``flask run``, you can copy that configuration and
-change the *Parameters* argument to run a different CLI command.
diff --git a/docs/config.rst b/docs/config.rst
deleted file mode 100644
index 5695bbd0..00000000
--- a/docs/config.rst
+++ /dev/null
@@ -1,836 +0,0 @@
-Configuration Handling
-======================
-
-Applications need some kind of configuration. There are different settings
-you might want to change depending on the application environment like
-toggling the debug mode, setting the secret key, and other such
-environment-specific things.
-
-The way Flask is designed usually requires the configuration to be
-available when the application starts up. You can hard code the
-configuration in the code, which for many small applications is not
-actually that bad, but there are better ways.
-
-Independent of how you load your config, there is a config object
-available which holds the loaded configuration values:
-The :attr:`~flask.Flask.config` attribute of the :class:`~flask.Flask`
-object. This is the place where Flask itself puts certain configuration
-values and also where extensions can put their configuration values. But
-this is also where you can have your own configuration.
-
-
-Configuration Basics
---------------------
-
-The :attr:`~flask.Flask.config` is actually a subclass of a dictionary and
-can be modified just like any dictionary::
-
- app = Flask(__name__)
- app.config['TESTING'] = True
-
-Certain configuration values are also forwarded to the
-:attr:`~flask.Flask` object so you can read and write them from there::
-
- app.testing = True
-
-To update multiple keys at once you can use the :meth:`dict.update`
-method::
-
- app.config.update(
- TESTING=True,
- SECRET_KEY='192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
- )
-
-
-Debug Mode
-----------
-
-The :data:`DEBUG` config value is special because it may behave inconsistently if
-changed after the app has begun setting up. In order to set debug mode reliably, use the
-``--debug`` option on the ``flask`` or ``flask run`` command. ``flask run`` will use the
-interactive debugger and reloader by default in debug mode.
-
-.. code-block:: text
-
- $ flask --app hello run --debug
-
-Using the option is recommended. While it is possible to set :data:`DEBUG` in your
-config or code, this is strongly discouraged. It can't be read early by the
-``flask run`` command, and some systems or extensions may have already configured
-themselves based on a previous value.
-
-
-Builtin Configuration Values
-----------------------------
-
-The following configuration values are used internally by Flask:
-
-.. py:data:: DEBUG
-
- Whether debug mode is enabled. When using ``flask run`` to start the development
- server, an interactive debugger will be shown for unhandled exceptions, and the
- server will be reloaded when code changes. The :attr:`~flask.Flask.debug` attribute
- maps to this config key. This is set with the ``FLASK_DEBUG`` environment variable.
- It may not behave as expected if set in code.
-
- **Do not enable debug mode when deploying in production.**
-
- Default: ``False``
-
-.. py:data:: TESTING
-
- Enable testing mode. Exceptions are propagated rather than handled by the
- the app's error handlers. Extensions may also change their behavior to
- facilitate easier testing. You should enable this in your own tests.
-
- Default: ``False``
-
-.. py:data:: PROPAGATE_EXCEPTIONS
-
- Exceptions are re-raised rather than being handled by the app's error
- handlers. If not set, this is implicitly true if ``TESTING`` or ``DEBUG``
- is enabled.
-
- Default: ``None``
-
-.. py:data:: TRAP_HTTP_EXCEPTIONS
-
- If there is no handler for an ``HTTPException``-type exception, re-raise it
- to be handled by the interactive debugger instead of returning it as a
- simple error response.
-
- Default: ``False``
-
-.. py:data:: TRAP_BAD_REQUEST_ERRORS
-
- Trying to access a key that doesn't exist from request dicts like ``args``
- and ``form`` will return a 400 Bad Request error page. Enable this to treat
- the error as an unhandled exception instead so that you get the interactive
- debugger. This is a more specific version of ``TRAP_HTTP_EXCEPTIONS``. If
- unset, it is enabled in debug mode.
-
- Default: ``None``
-
-.. py:data:: SECRET_KEY
-
- A secret key that will be used for securely signing the session cookie
- and can be used for any other security related needs by extensions or your
- application. It should be a long random ``bytes`` or ``str``. For
- example, copy the output of this to your config::
-
- $ python -c 'import secrets; print(secrets.token_hex())'
- '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
-
- **Do not reveal the secret key when posting questions or committing code.**
-
- Default: ``None``
-
-.. py:data:: SECRET_KEY_FALLBACKS
-
- A list of old secret keys that can still be used for unsigning, most recent
- first. This allows a project to implement key rotation without invalidating
- active sessions or other recently-signed secrets.
-
- Keys should be removed after an appropriate period of time, as checking each
- additional key adds some overhead.
-
- Flask's built-in secure cookie session supports this. Extensions that use
- :data:`SECRET_KEY` may not support this yet.
-
- Default: ``None``
-
- .. versionadded:: 3.1
-
-.. py:data:: SESSION_COOKIE_NAME
-
- The name of the session cookie. Can be changed in case you already have a
- cookie with the same name.
-
- Default: ``'session'``
-
-.. py:data:: SESSION_COOKIE_DOMAIN
-
- The value of the ``Domain`` parameter on the session cookie. If not set, browsers
- will only send the cookie to the exact domain it was set from. Otherwise, they
- will send it to any subdomain of the given value as well.
-
- Not setting this value is more restricted and secure than setting it.
-
- Default: ``None``
-
- .. warning::
- If this is changed after the browser created a cookie is created with
- one setting, it may result in another being created. Browsers may send
- send both in an undefined order. In that case, you may want to change
- :data:`SESSION_COOKIE_NAME` as well or otherwise invalidate old sessions.
-
- .. versionchanged:: 2.3
- Not set by default, does not fall back to ``SERVER_NAME``.
-
-.. py:data:: SESSION_COOKIE_PATH
-
- The path that the session cookie will be valid for. If not set, the cookie
- will be valid underneath ``APPLICATION_ROOT`` or ``/`` if that is not set.
-
- Default: ``None``
-
-.. py:data:: SESSION_COOKIE_HTTPONLY
-
- Browsers will not allow JavaScript access to cookies marked as "HTTP only"
- for security.
-
- Default: ``True``
-
-.. py:data:: SESSION_COOKIE_SECURE
-
- Browsers will only send cookies with requests over HTTPS if the cookie is
- marked "secure". The application must be served over HTTPS for this to make
- sense.
-
- Default: ``False``
-
-.. py:data:: SESSION_COOKIE_PARTITIONED
-
- Browsers will send cookies based on the top-level document's domain, rather
- than only the domain of the document setting the cookie. This prevents third
- party cookies set in iframes from "leaking" between separate sites.
-
- Browsers are beginning to disallow non-partitioned third party cookies, so
- you need to mark your cookies partitioned if you expect them to work in such
- embedded situations.
-
- Enabling this implicitly enables :data:`SESSION_COOKIE_SECURE` as well, as
- it is only valid when served over HTTPS.
-
- Default: ``False``
-
- .. versionadded:: 3.1
-
-.. py:data:: SESSION_COOKIE_SAMESITE
-
- Restrict how cookies are sent with requests from external sites. Can
- be set to ``'Lax'`` (recommended) or ``'Strict'``.
- See :ref:`security-cookie`.
-
- Default: ``None``
-
- .. versionadded:: 1.0
-
-.. py:data:: PERMANENT_SESSION_LIFETIME
-
- If ``session.permanent`` is true, the cookie's expiration will be set this
- number of seconds in the future. Can either be a
- :class:`datetime.timedelta` or an ``int``.
-
- Flask's default cookie implementation validates that the cryptographic
- signature is not older than this value.
-
- Default: ``timedelta(days=31)`` (``2678400`` seconds)
-
-.. py:data:: SESSION_REFRESH_EACH_REQUEST
-
- Control whether the cookie is sent with every response when
- ``session.permanent`` is true. Sending the cookie every time (the default)
- can more reliably keep the session from expiring, but uses more bandwidth.
- Non-permanent sessions are not affected.
-
- Default: ``True``
-
-.. py:data:: USE_X_SENDFILE
-
- When serving files, set the ``X-Sendfile`` header instead of serving the
- data with Flask. Some web servers, such as Apache, recognize this and serve
- the data more efficiently. This only makes sense when using such a server.
-
- Default: ``False``
-
-.. py:data:: SEND_FILE_MAX_AGE_DEFAULT
-
- When serving files, set the cache control max age to this number of
- seconds. Can be a :class:`datetime.timedelta` or an ``int``.
- Override this value on a per-file basis using
- :meth:`~flask.Flask.get_send_file_max_age` on the application or
- blueprint.
-
- If ``None``, ``send_file`` tells the browser to use conditional
- requests will be used instead of a timed cache, which is usually
- preferable.
-
- Default: ``None``
-
-.. py:data:: TRUSTED_HOSTS
-
- Validate :attr:`.Request.host` and other attributes that use it against
- these trusted values. Raise a :exc:`~werkzeug.exceptions.SecurityError` if
- the host is invalid, which results in a 400 error. If it is ``None``, all
- hosts are valid. Each value is either an exact match, or can start with
- a dot ``.`` to match any subdomain.
-
- Validation is done during routing against this value. ``before_request`` and
- ``after_request`` callbacks will still be called.
-
- Default: ``None``
-
- .. versionadded:: 3.1
-
-.. py:data:: SERVER_NAME
-
- Inform the application what host and port it is bound to.
-
- Must be set if ``subdomain_matching`` is enabled, to be able to extract the
- subdomain from the request.
-
- Must be set for ``url_for`` to generate external URLs outside of a
- request context.
-
- Default: ``None``
-
- .. versionchanged:: 3.1
- Does not restrict requests to only this domain, for both
- ``subdomain_matching`` and ``host_matching``.
-
- .. versionchanged:: 1.0
- Does not implicitly enable ``subdomain_matching``.
-
- .. versionchanged:: 2.3
- Does not affect ``SESSION_COOKIE_DOMAIN``.
-
-.. py:data:: APPLICATION_ROOT
-
- Inform the application what path it is mounted under by the application /
- web server. This is used for generating URLs outside the context of a
- request (inside a request, the dispatcher is responsible for setting
- ``SCRIPT_NAME`` instead; see :doc:`/patterns/appdispatch`
- for examples of dispatch configuration).
-
- Will be used for the session cookie path if ``SESSION_COOKIE_PATH`` is not
- set.
-
- Default: ``'/'``
-
-.. py:data:: PREFERRED_URL_SCHEME
-
- Use this scheme for generating external URLs when not in a request context.
-
- Default: ``'http'``
-
-.. py:data:: MAX_CONTENT_LENGTH
-
- The maximum number of bytes that will be read during this request. If
- this limit is exceeded, a 413 :exc:`~werkzeug.exceptions.RequestEntityTooLarge`
- error is raised. If it is set to ``None``, no limit is enforced at the
- Flask application level. However, if it is ``None`` and the request has no
- ``Content-Length`` header and the WSGI server does not indicate that it
- terminates the stream, then no data is read to avoid an infinite stream.
-
- Each request defaults to this config. It can be set on a specific
- :attr:`.Request.max_content_length` to apply the limit to that specific
- view. This should be set appropriately based on an application's or view's
- specific needs.
-
- Default: ``None``
-
- .. versionadded:: 0.6
-
-.. py:data:: MAX_FORM_MEMORY_SIZE
-
- The maximum size in bytes any non-file form field may be in a
- ``multipart/form-data`` body. If this limit is exceeded, a 413
- :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it is
- set to ``None``, no limit is enforced at the Flask application level.
-
- Each request defaults to this config. It can be set on a specific
- :attr:`.Request.max_form_memory_parts` to apply the limit to that specific
- view. This should be set appropriately based on an application's or view's
- specific needs.
-
- Default: ``500_000``
-
- .. versionadded:: 3.1
-
-.. py:data:: MAX_FORM_PARTS
-
- The maximum number of fields that may be present in a
- ``multipart/form-data`` body. If this limit is exceeded, a 413
- :exc:`~werkzeug.exceptions.RequestEntityTooLarge` error is raised. If it
- is set to ``None``, no limit is enforced at the Flask application level.
-
- Each request defaults to this config. It can be set on a specific
- :attr:`.Request.max_form_parts` to apply the limit to that specific view.
- This should be set appropriately based on an application's or view's
- specific needs.
-
- Default: ``1_000``
-
- .. versionadded:: 3.1
-
-.. py:data:: TEMPLATES_AUTO_RELOAD
-
- Reload templates when they are changed. If not set, it will be enabled in
- debug mode.
-
- Default: ``None``
-
-.. py:data:: EXPLAIN_TEMPLATE_LOADING
-
- Log debugging information tracing how a template file was loaded. This can
- be useful to figure out why a template was not loaded or the wrong file
- appears to be loaded.
-
- Default: ``False``
-
-.. py:data:: MAX_COOKIE_SIZE
-
- Warn if cookie headers are larger than this many bytes. Defaults to
- ``4093``. Larger cookies may be silently ignored by browsers. Set to
- ``0`` to disable the warning.
-
-.. py:data:: PROVIDE_AUTOMATIC_OPTIONS
-
- Set to ``False`` to disable the automatic addition of OPTIONS
- responses. This can be overridden per route by altering the
- ``provide_automatic_options`` attribute.
-
-.. versionadded:: 0.4
- ``LOGGER_NAME``
-
-.. versionadded:: 0.5
- ``SERVER_NAME``
-
-.. versionadded:: 0.6
- ``MAX_CONTENT_LENGTH``
-
-.. versionadded:: 0.7
- ``PROPAGATE_EXCEPTIONS``, ``PRESERVE_CONTEXT_ON_EXCEPTION``
-
-.. versionadded:: 0.8
- ``TRAP_BAD_REQUEST_ERRORS``, ``TRAP_HTTP_EXCEPTIONS``,
- ``APPLICATION_ROOT``, ``SESSION_COOKIE_DOMAIN``,
- ``SESSION_COOKIE_PATH``, ``SESSION_COOKIE_HTTPONLY``,
- ``SESSION_COOKIE_SECURE``
-
-.. versionadded:: 0.9
- ``PREFERRED_URL_SCHEME``
-
-.. versionadded:: 0.10
- ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_PRETTYPRINT_REGULAR``
-
-.. versionadded:: 0.11
- ``SESSION_REFRESH_EACH_REQUEST``, ``TEMPLATES_AUTO_RELOAD``,
- ``LOGGER_HANDLER_POLICY``, ``EXPLAIN_TEMPLATE_LOADING``
-
-.. versionchanged:: 1.0
- ``LOGGER_NAME`` and ``LOGGER_HANDLER_POLICY`` were removed. See
- :doc:`/logging` for information about configuration.
-
- Added :data:`ENV` to reflect the :envvar:`FLASK_ENV` environment
- variable.
-
- Added :data:`SESSION_COOKIE_SAMESITE` to control the session
- cookie's ``SameSite`` option.
-
- Added :data:`MAX_COOKIE_SIZE` to control a warning from Werkzeug.
-
-.. versionchanged:: 2.2
- Removed ``PRESERVE_CONTEXT_ON_EXCEPTION``.
-
-.. versionchanged:: 2.3
- ``JSON_AS_ASCII``, ``JSON_SORT_KEYS``, ``JSONIFY_MIMETYPE``, and
- ``JSONIFY_PRETTYPRINT_REGULAR`` were removed. The default ``app.json`` provider has
- equivalent attributes instead.
-
-.. versionchanged:: 2.3
- ``ENV`` was removed.
-
-.. versionadded:: 3.10
- Added :data:`PROVIDE_AUTOMATIC_OPTIONS` to control the default
- addition of autogenerated OPTIONS responses.
-
-
-Configuring from Python Files
------------------------------
-
-Configuration becomes more useful if you can store it in a separate file, ideally
-located outside the actual application package. You can deploy your application, then
-separately configure it for the specific deployment.
-
-A common pattern is this::
-
- app = Flask(__name__)
- app.config.from_object('yourapplication.default_settings')
- app.config.from_envvar('YOURAPPLICATION_SETTINGS')
-
-This first loads the configuration from the
-`yourapplication.default_settings` module and then overrides the values
-with the contents of the file the :envvar:`YOURAPPLICATION_SETTINGS`
-environment variable points to. This environment variable can be set
-in the shell before starting the server:
-
-.. tabs::
-
- .. group-tab:: Bash
-
- .. code-block:: text
-
- $ export YOURAPPLICATION_SETTINGS=/path/to/settings.cfg
- $ flask run
- * Running on http://127.0.0.1:5000/
-
- .. group-tab:: Fish
-
- .. code-block:: text
-
- $ set -x YOURAPPLICATION_SETTINGS /path/to/settings.cfg
- $ flask run
- * Running on http://127.0.0.1:5000/
-
- .. group-tab:: CMD
-
- .. code-block:: text
-
- > set YOURAPPLICATION_SETTINGS=\path\to\settings.cfg
- > flask run
- * Running on http://127.0.0.1:5000/
-
- .. group-tab:: Powershell
-
- .. code-block:: text
-
- > $env:YOURAPPLICATION_SETTINGS = "\path\to\settings.cfg"
- > flask run
- * Running on http://127.0.0.1:5000/
-
-The configuration files themselves are actual Python files. Only values
-in uppercase are actually stored in the config object later on. So make
-sure to use uppercase letters for your config keys.
-
-Here is an example of a configuration file::
-
- # Example configuration
- SECRET_KEY = '192b9bdd22ab9ed4d12e236c78afcb9a393ec15f71bbf5dc987d54727823bcbf'
-
-Make sure to load the configuration very early on, so that extensions have
-the ability to access the configuration when starting up. There are other
-methods on the config object as well to load from individual files. For a
-complete reference, read the :class:`~flask.Config` object's
-documentation.
-
-
-Configuring from Data Files
----------------------------
-
-It is also possible to load configuration from a file in a format of
-your choice using :meth:`~flask.Config.from_file`. For example to load
-from a TOML file:
-
-.. code-block:: python
-
- import tomllib
- app.config.from_file("config.toml", load=tomllib.load, text=False)
-
-Or from a JSON file:
-
-.. code-block:: python
-
- import json
- app.config.from_file("config.json", load=json.load)
-
-
-Configuring from Environment Variables
---------------------------------------
-
-In addition to pointing to configuration files using environment
-variables, you may find it useful (or necessary) to control your
-configuration values directly from the environment. Flask can be
-instructed to load all environment variables starting with a specific
-prefix into the config using :meth:`~flask.Config.from_prefixed_env`.
-
-Environment variables can be set in the shell before starting the
-server:
-
-.. tabs::
-
- .. group-tab:: Bash
-
- .. code-block:: text
-
- $ export FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f"
- $ export FLASK_MAIL_ENABLED=false
- $ flask run
- * Running on http://127.0.0.1:5000/
-
- .. group-tab:: Fish
-
- .. code-block:: text
-
- $ set -x FLASK_SECRET_KEY "5f352379324c22463451387a0aec5d2f"
- $ set -x FLASK_MAIL_ENABLED false
- $ flask run
- * Running on http://127.0.0.1:5000/
-
- .. group-tab:: CMD
-
- .. code-block:: text
-
- > set FLASK_SECRET_KEY="5f352379324c22463451387a0aec5d2f"
- > set FLASK_MAIL_ENABLED=false
- > flask run
- * Running on http://127.0.0.1:5000/
-
- .. group-tab:: Powershell
-
- .. code-block:: text
-
- > $env:FLASK_SECRET_KEY = "5f352379324c22463451387a0aec5d2f"
- > $env:FLASK_MAIL_ENABLED = "false"
- > flask run
- * Running on http://127.0.0.1:5000/
-
-The variables can then be loaded and accessed via the config with a key
-equal to the environment variable name without the prefix i.e.
-
-.. code-block:: python
-
- app.config.from_prefixed_env()
- app.config["SECRET_KEY"] # Is "5f352379324c22463451387a0aec5d2f"
-
-The prefix is ``FLASK_`` by default. This is configurable via the
-``prefix`` argument of :meth:`~flask.Config.from_prefixed_env`.
-
-Values will be parsed to attempt to convert them to a more specific type
-than strings. By default :func:`json.loads` is used, so any valid JSON
-value is possible, including lists and dicts. This is configurable via
-the ``loads`` argument of :meth:`~flask.Config.from_prefixed_env`.
-
-When adding a boolean value with the default JSON parsing, only "true"
-and "false", lowercase, are valid values. Keep in mind that any
-non-empty string is considered ``True`` by Python.
-
-It is possible to set keys in nested dictionaries by separating the
-keys with double underscore (``__``). Any intermediate keys that don't
-exist on the parent dict will be initialized to an empty dict.
-
-.. code-block:: text
-
- $ export FLASK_MYAPI__credentials__username=user123
-
-.. code-block:: python
-
- app.config["MYAPI"]["credentials"]["username"] # Is "user123"
-
-On Windows, environment variable keys are always uppercase, therefore
-the above example would end up as ``MYAPI__CREDENTIALS__USERNAME``.
-
-For even more config loading features, including merging and
-case-insensitive Windows support, try a dedicated library such as
-Dynaconf_, which includes integration with Flask.
-
-.. _Dynaconf: https://www.dynaconf.com/
-
-
-Configuration Best Practices
-----------------------------
-
-The downside with the approach mentioned earlier is that it makes testing
-a little harder. There is no single 100% solution for this problem in
-general, but there are a couple of things you can keep in mind to improve
-that experience:
-
-1. Create your application in a function and register blueprints on it.
- That way you can create multiple instances of your application with
- different configurations attached which makes unit testing a lot
- easier. You can use this to pass in configuration as needed.
-
-2. Do not write code that needs the configuration at import time. If you
- limit yourself to request-only accesses to the configuration you can
- reconfigure the object later on as needed.
-
-3. Make sure to load the configuration very early on, so that
- extensions can access the configuration when calling ``init_app``.
-
-
-.. _config-dev-prod:
-
-Development / Production
-------------------------
-
-Most applications need more than one configuration. There should be at
-least separate configurations for the production server and the one used
-during development. The easiest way to handle this is to use a default
-configuration that is always loaded and part of the version control, and a
-separate configuration that overrides the values as necessary as mentioned
-in the example above::
-
- app = Flask(__name__)
- app.config.from_object('yourapplication.default_settings')
- app.config.from_envvar('YOURAPPLICATION_SETTINGS')
-
-Then you just have to add a separate :file:`config.py` file and export
-``YOURAPPLICATION_SETTINGS=/path/to/config.py`` and you are done. However
-there are alternative ways as well. For example you could use imports or
-subclassing.
-
-What is very popular in the Django world is to make the import explicit in
-the config file by adding ``from yourapplication.default_settings
-import *`` to the top of the file and then overriding the changes by hand.
-You could also inspect an environment variable like
-``YOURAPPLICATION_MODE`` and set that to `production`, `development` etc
-and import different hard-coded files based on that.
-
-An interesting pattern is also to use classes and inheritance for
-configuration::
-
- class Config(object):
- TESTING = False
-
- class ProductionConfig(Config):
- DATABASE_URI = 'mysql://user@localhost/foo'
-
- class DevelopmentConfig(Config):
- DATABASE_URI = "sqlite:////tmp/foo.db"
-
- class TestingConfig(Config):
- DATABASE_URI = 'sqlite:///:memory:'
- TESTING = True
-
-To enable such a config you just have to call into
-:meth:`~flask.Config.from_object`::
-
- app.config.from_object('configmodule.ProductionConfig')
-
-Note that :meth:`~flask.Config.from_object` does not instantiate the class
-object. If you need to instantiate the class, such as to access a property,
-then you must do so before calling :meth:`~flask.Config.from_object`::
-
- from configmodule import ProductionConfig
- app.config.from_object(ProductionConfig())
-
- # Alternatively, import via string:
- from werkzeug.utils import import_string
- cfg = import_string('configmodule.ProductionConfig')()
- app.config.from_object(cfg)
-
-Instantiating the configuration object allows you to use ``@property`` in
-your configuration classes::
-
- class Config(object):
- """Base config, uses staging database server."""
- TESTING = False
- DB_SERVER = '192.168.1.56'
-
- @property
- def DATABASE_URI(self): # Note: all caps
- return f"mysql://user@{self.DB_SERVER}/foo"
-
- class ProductionConfig(Config):
- """Uses production database server."""
- DB_SERVER = '192.168.19.32'
-
- class DevelopmentConfig(Config):
- DB_SERVER = 'localhost'
-
- class TestingConfig(Config):
- DB_SERVER = 'localhost'
- DATABASE_URI = 'sqlite:///:memory:'
-
-There are many different ways and it's up to you how you want to manage
-your configuration files. However here a list of good recommendations:
-
-- Keep a default configuration in version control. Either populate the
- config with this default configuration or import it in your own
- configuration files before overriding values.
-- Use an environment variable to switch between the configurations.
- This can be done from outside the Python interpreter and makes
- development and deployment much easier because you can quickly and
- easily switch between different configs without having to touch the
- code at all. If you are working often on different projects you can
- even create your own script for sourcing that activates a virtualenv
- and exports the development configuration for you.
-- Use a tool like `fabric`_ to push code and configuration separately
- to the production server(s).
-
-.. _fabric: https://www.fabfile.org/
-
-
-.. _instance-folders:
-
-Instance Folders
-----------------
-
-.. versionadded:: 0.8
-
-Flask 0.8 introduces instance folders. Flask for a long time made it
-possible to refer to paths relative to the application's folder directly
-(via :attr:`Flask.root_path`). This was also how many developers loaded
-configurations stored next to the application. Unfortunately however this
-only works well if applications are not packages in which case the root
-path refers to the contents of the package.
-
-With Flask 0.8 a new attribute was introduced:
-:attr:`Flask.instance_path`. It refers to a new concept called the
-“instance folder”. The instance folder is designed to not be under
-version control and be deployment specific. It's the perfect place to
-drop things that either change at runtime or configuration files.
-
-You can either explicitly provide the path of the instance folder when
-creating the Flask application or you can let Flask autodetect the
-instance folder. For explicit configuration use the `instance_path`
-parameter::
-
- app = Flask(__name__, instance_path='/path/to/instance/folder')
-
-Please keep in mind that this path *must* be absolute when provided.
-
-If the `instance_path` parameter is not provided the following default
-locations are used:
-
-- Uninstalled module::
-
- /myapp.py
- /instance
-
-- Uninstalled package::
-
- /myapp
- /__init__.py
- /instance
-
-- Installed module or package::
-
- $PREFIX/lib/pythonX.Y/site-packages/myapp
- $PREFIX/var/myapp-instance
-
- ``$PREFIX`` is the prefix of your Python installation. This can be
- ``/usr`` or the path to your virtualenv. You can print the value of
- ``sys.prefix`` to see what the prefix is set to.
-
-Since the config object provided loading of configuration files from
-relative filenames we made it possible to change the loading via filenames
-to be relative to the instance path if wanted. The behavior of relative
-paths in config files can be flipped between “relative to the application
-root” (the default) to “relative to instance folder” via the
-`instance_relative_config` switch to the application constructor::
-
- app = Flask(__name__, instance_relative_config=True)
-
-Here is a full example of how to configure Flask to preload the config
-from a module and then override the config from a file in the instance
-folder if it exists::
-
- app = Flask(__name__, instance_relative_config=True)
- app.config.from_object('yourapplication.default_settings')
- app.config.from_pyfile('application.cfg', silent=True)
-
-The path to the instance folder can be found via the
-:attr:`Flask.instance_path`. Flask also provides a shortcut to open a
-file from the instance folder with :meth:`Flask.open_instance_resource`.
-
-Example usage for both::
-
- filename = os.path.join(app.instance_path, 'application.cfg')
- with open(filename) as f:
- config = f.read()
-
- # or via open_instance_resource:
- with app.open_instance_resource('application.cfg') as f:
- config = f.read()
diff --git a/docs/contributing.rst b/docs/contributing.rst
deleted file mode 100644
index d44f865f..00000000
--- a/docs/contributing.rst
+++ /dev/null
@@ -1,8 +0,0 @@
-Contributing
-============
-
-See the Pallets `detailed contributing documentation <_contrib>`_ for many ways
-to contribute, including reporting issues, requesting features, asking or
-answering questions, and making PRs.
-
-.. _contrib: https://palletsprojects.com/contributing/
diff --git a/docs/debugging.rst b/docs/debugging.rst
deleted file mode 100644
index f6b56cab..00000000
--- a/docs/debugging.rst
+++ /dev/null
@@ -1,99 +0,0 @@
-Debugging Application Errors
-============================
-
-
-In Production
--------------
-
-**Do not run the development server, or enable the built-in debugger, in
-a production environment.** The debugger allows executing arbitrary
-Python code from the browser. It's protected by a pin, but that should
-not be relied on for security.
-
-Use an error logging tool, such as Sentry, as described in
-:ref:`error-logging-tools`, or enable logging and notifications as
-described in :doc:`/logging`.
-
-If you have access to the server, you could add some code to start an
-external debugger if ``request.remote_addr`` matches your IP. Some IDE
-debuggers also have a remote mode so breakpoints on the server can be
-interacted with locally. Only enable a debugger temporarily.
-
-
-The Built-In Debugger
----------------------
-
-The built-in Werkzeug development server provides a debugger which shows
-an interactive traceback in the browser when an unhandled error occurs
-during a request. This debugger should only be used during development.
-
-.. image:: _static/debugger.png
- :align: center
- :class: screenshot
- :alt: screenshot of debugger in action
-
-.. warning::
-
- The debugger allows executing arbitrary Python code from the
- browser. It is protected by a pin, but still represents a major
- security risk. Do not run the development server or debugger in a
- production environment.
-
-The debugger is enabled by default when the development server is run in debug mode.
-
-.. code-block:: text
-
- $ flask --app hello run --debug
-
-When running from Python code, passing ``debug=True`` enables debug mode, which is
-mostly equivalent.
-
-.. code-block:: python
-
- app.run(debug=True)
-
-:doc:`/server` and :doc:`/cli` have more information about running the debugger and
-debug mode. More information about the debugger can be found in the `Werkzeug
-documentation `__.
-
-
-External Debuggers
-------------------
-
-External debuggers, such as those provided by IDEs, can offer a more
-powerful debugging experience than the built-in debugger. They can also
-be used to step through code during a request before an error is raised,
-or if no error is raised. Some even have a remote mode so you can debug
-code running on another machine.
-
-When using an external debugger, the app should still be in debug mode, otherwise Flask
-turns unhandled errors into generic 500 error pages. However, the built-in debugger and
-reloader should be disabled so they don't interfere with the external debugger.
-
-.. code-block:: text
-
- $ flask --app hello run --debug --no-debugger --no-reload
-
-When running from Python:
-
-.. code-block:: python
-
- app.run(debug=True, use_debugger=False, use_reloader=False)
-
-Disabling these isn't required, an external debugger will continue to work with the
-following caveats.
-
-- If the built-in debugger is not disabled, it will catch unhandled exceptions before
- the external debugger can.
-- If the reloader is not disabled, it could cause an unexpected reload if code changes
- during a breakpoint.
-- The development server will still catch unhandled exceptions if the built-in
- debugger is disabled, otherwise it would crash on any error. If you want that (and
- usually you don't) pass ``passthrough_errors=True`` to ``app.run``.
-
- .. code-block:: python
-
- app.run(
- debug=True, passthrough_errors=True,
- use_debugger=False, use_reloader=False
- )
diff --git a/docs/deploying/apache-httpd.rst b/docs/deploying/apache-httpd.rst
deleted file mode 100644
index bdeaf626..00000000
--- a/docs/deploying/apache-httpd.rst
+++ /dev/null
@@ -1,66 +0,0 @@
-Apache httpd
-============
-
-`Apache httpd`_ is a fast, production level HTTP server. When serving
-your application with one of the WSGI servers listed in :doc:`index`, it
-is often good or necessary to put a dedicated HTTP server in front of
-it. This "reverse proxy" can handle incoming requests, TLS, and other
-security and performance concerns better than the WSGI server.
-
-httpd can be installed using your system package manager, or a pre-built
-executable for Windows. Installing and running httpd itself is outside
-the scope of this doc. This page outlines the basics of configuring
-httpd to proxy your application. Be sure to read its documentation to
-understand what features are available.
-
-.. _Apache httpd: https://httpd.apache.org/
-
-
-Domain Name
------------
-
-Acquiring and configuring a domain name is outside the scope of this
-doc. In general, you will buy a domain name from a registrar, pay for
-server space with a hosting provider, and then point your registrar
-at the hosting provider's name servers.
-
-To simulate this, you can also edit your ``hosts`` file, located at
-``/etc/hosts`` on Linux. Add a line that associates a name with the
-local IP.
-
-Modern Linux systems may be configured to treat any domain name that
-ends with ``.localhost`` like this without adding it to the ``hosts``
-file.
-
-.. code-block:: python
- :caption: ``/etc/hosts``
-
- 127.0.0.1 hello.localhost
-
-
-Configuration
--------------
-
-The httpd configuration is located at ``/etc/httpd/conf/httpd.conf`` on
-Linux. It may be different depending on your operating system. Check the
-docs and look for ``httpd.conf``.
-
-Remove or comment out any existing ``DocumentRoot`` directive. Add the
-config lines below. We'll assume the WSGI server is listening locally at
-``http://127.0.0.1:8000``.
-
-.. code-block:: apache
- :caption: ``/etc/httpd/conf/httpd.conf``
-
- LoadModule proxy_module modules/mod_proxy.so
- LoadModule proxy_http_module modules/mod_proxy_http.so
- ProxyPass / http://127.0.0.1:8000/
- RequestHeader set X-Forwarded-Proto http
- RequestHeader set X-Forwarded-Prefix /
-
-The ``LoadModule`` lines might already exist. If so, make sure they are
-uncommented instead of adding them manually.
-
-Then :doc:`proxy_fix` so that your application uses the ``X-Forwarded``
-headers. ``X-Forwarded-For`` and ``X-Forwarded-Host`` are automatically
-set by ``ProxyPass``.
diff --git a/docs/deploying/asgi.rst b/docs/deploying/asgi.rst
deleted file mode 100644
index 1dc0aa24..00000000
--- a/docs/deploying/asgi.rst
+++ /dev/null
@@ -1,27 +0,0 @@
-ASGI
-====
-
-If you'd like to use an ASGI server you will need to utilise WSGI to
-ASGI middleware. The asgiref
-`WsgiToAsgi `_
-adapter is recommended as it integrates with the event loop used for
-Flask's :ref:`async_await` support. You can use the adapter by
-wrapping the Flask app,
-
-.. code-block:: python
-
- from asgiref.wsgi import WsgiToAsgi
- from flask import Flask
-
- app = Flask(__name__)
-
- ...
-
- asgi_app = WsgiToAsgi(app)
-
-and then serving the ``asgi_app`` with the ASGI server, e.g. using
-`Hypercorn `_,
-
-.. sourcecode:: text
-
- $ hypercorn module:asgi_app
diff --git a/docs/deploying/eventlet.rst b/docs/deploying/eventlet.rst
deleted file mode 100644
index 8a718b22..00000000
--- a/docs/deploying/eventlet.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-eventlet
-========
-
-Prefer using :doc:`gunicorn` with eventlet workers rather than using
-`eventlet`_ directly. Gunicorn provides a much more configurable and
-production-tested server.
-
-`eventlet`_ allows writing asynchronous, coroutine-based code that looks
-like standard synchronous Python. It uses `greenlet`_ to enable task
-switching without writing ``async/await`` or using ``asyncio``.
-
-:doc:`gevent` is another library that does the same thing. Certain
-dependencies you have, or other considerations, may affect which of the
-two you choose to use.
-
-eventlet provides a WSGI server that can handle many connections at once
-instead of one per worker process. You must actually use eventlet in
-your own code to see any benefit to using the server.
-
-.. _eventlet: https://eventlet.net/
-.. _greenlet: https://greenlet.readthedocs.io/en/latest/
-
-
-Installing
-----------
-
-When using eventlet, greenlet>=1.0 is required, otherwise context locals
-such as ``request`` will not work as expected. When using PyPy,
-PyPy>=7.3.7 is required.
-
-Create a virtualenv, install your application, then install
-``eventlet``.
-
-.. code-block:: text
-
- $ cd hello-app
- $ python -m venv .venv
- $ . .venv/bin/activate
- $ pip install . # install your application
- $ pip install eventlet
-
-
-Running
--------
-
-To use eventlet to serve your application, write a script that imports
-its ``wsgi.server``, as well as your app or app factory.
-
-.. code-block:: python
- :caption: ``wsgi.py``
-
- import eventlet
- from eventlet import wsgi
- from hello import create_app
-
- app = create_app()
- wsgi.server(eventlet.listen(("127.0.0.1", 8000)), app)
-
-.. code-block:: text
-
- $ python wsgi.py
- (x) wsgi starting up on http://127.0.0.1:8000
-
-
-Binding Externally
-------------------
-
-eventlet should not be run as root because it would cause your
-application code to run as root, which is not secure. However, this
-means it will not be possible to bind to port 80 or 443. Instead, a
-reverse proxy such as :doc:`nginx` or :doc:`apache-httpd` should be used
-in front of eventlet.
-
-You can bind to all external IPs on a non-privileged port by using
-``0.0.0.0`` in the server arguments shown in the previous section.
-Don't do this when using a reverse proxy setup, otherwise it will be
-possible to bypass the proxy.
-
-``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
-IP address in your browser.
diff --git a/docs/deploying/gevent.rst b/docs/deploying/gevent.rst
deleted file mode 100644
index 448b93e7..00000000
--- a/docs/deploying/gevent.rst
+++ /dev/null
@@ -1,80 +0,0 @@
-gevent
-======
-
-Prefer using :doc:`gunicorn` or :doc:`uwsgi` with gevent workers rather
-than using `gevent`_ directly. Gunicorn and uWSGI provide much more
-configurable and production-tested servers.
-
-`gevent`_ allows writing asynchronous, coroutine-based code that looks
-like standard synchronous Python. It uses `greenlet`_ to enable task
-switching without writing ``async/await`` or using ``asyncio``.
-
-:doc:`eventlet` is another library that does the same thing. Certain
-dependencies you have, or other considerations, may affect which of the
-two you choose to use.
-
-gevent provides a WSGI server that can handle many connections at once
-instead of one per worker process. You must actually use gevent in your
-own code to see any benefit to using the server.
-
-.. _gevent: https://www.gevent.org/
-.. _greenlet: https://greenlet.readthedocs.io/en/latest/
-
-
-Installing
-----------
-
-When using gevent, greenlet>=1.0 is required, otherwise context locals
-such as ``request`` will not work as expected. When using PyPy,
-PyPy>=7.3.7 is required.
-
-Create a virtualenv, install your application, then install ``gevent``.
-
-.. code-block:: text
-
- $ cd hello-app
- $ python -m venv .venv
- $ . .venv/bin/activate
- $ pip install . # install your application
- $ pip install gevent
-
-
-Running
--------
-
-To use gevent to serve your application, write a script that imports its
-``WSGIServer``, as well as your app or app factory.
-
-.. code-block:: python
- :caption: ``wsgi.py``
-
- from gevent.pywsgi import WSGIServer
- from hello import create_app
-
- app = create_app()
- http_server = WSGIServer(("127.0.0.1", 8000), app)
- http_server.serve_forever()
-
-.. code-block:: text
-
- $ python wsgi.py
-
-No output is shown when the server starts.
-
-
-Binding Externally
-------------------
-
-gevent should not be run as root because it would cause your
-application code to run as root, which is not secure. However, this
-means it will not be possible to bind to port 80 or 443. Instead, a
-reverse proxy such as :doc:`nginx` or :doc:`apache-httpd` should be used
-in front of gevent.
-
-You can bind to all external IPs on a non-privileged port by using
-``0.0.0.0`` in the server arguments shown in the previous section. Don't
-do this when using a reverse proxy setup, otherwise it will be possible
-to bypass the proxy.
-
-``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
-IP address in your browser.
diff --git a/docs/deploying/gunicorn.rst b/docs/deploying/gunicorn.rst
deleted file mode 100644
index c50edc23..00000000
--- a/docs/deploying/gunicorn.rst
+++ /dev/null
@@ -1,130 +0,0 @@
-Gunicorn
-========
-
-`Gunicorn`_ is a pure Python WSGI server with simple configuration and
-multiple worker implementations for performance tuning.
-
-* It tends to integrate easily with hosting platforms.
-* It does not support Windows (but does run on WSL).
-* It is easy to install as it does not require additional dependencies
- or compilation.
-* It has built-in async worker support using gevent or eventlet.
-
-This page outlines the basics of running Gunicorn. Be sure to read its
-`documentation`_ and use ``gunicorn --help`` to understand what features
-are available.
-
-.. _Gunicorn: https://gunicorn.org/
-.. _documentation: https://docs.gunicorn.org/
-
-
-Installing
-----------
-
-Gunicorn is easy to install, as it does not require external
-dependencies or compilation. It runs on Windows only under WSL.
-
-Create a virtualenv, install your application, then install
-``gunicorn``.
-
-.. code-block:: text
-
- $ cd hello-app
- $ python -m venv .venv
- $ . .venv/bin/activate
- $ pip install . # install your application
- $ pip install gunicorn
-
-
-Running
--------
-
-The only required argument to Gunicorn tells it how to load your Flask
-application. The syntax is ``{module_import}:{app_variable}``.
-``module_import`` is the dotted import name to the module with your
-application. ``app_variable`` is the variable with the application. It
-can also be a function call (with any arguments) if you're using the
-app factory pattern.
-
-.. code-block:: text
-
- # equivalent to 'from hello import app'
- $ gunicorn -w 4 'hello:app'
-
- # equivalent to 'from hello import create_app; create_app()'
- $ gunicorn -w 4 'hello:create_app()'
-
- Starting gunicorn 20.1.0
- Listening at: http://127.0.0.1:8000 (x)
- Using worker: sync
- Booting worker with pid: x
- Booting worker with pid: x
- Booting worker with pid: x
- Booting worker with pid: x
-
-The ``-w`` option specifies the number of processes to run; a starting
-value could be ``CPU * 2``. The default is only 1 worker, which is
-probably not what you want for the default worker type.
-
-Logs for each request aren't shown by default, only worker info and
-errors are shown. To show access logs on stdout, use the
-``--access-logfile=-`` option.
-
-
-Binding Externally
-------------------
-
-Gunicorn should not be run as root because it would cause your
-application code to run as root, which is not secure. However, this
-means it will not be possible to bind to port 80 or 443. Instead, a
-reverse proxy such as :doc:`nginx` or :doc:`apache-httpd` should be used
-in front of Gunicorn.
-
-You can bind to all external IPs on a non-privileged port using the
-``-b 0.0.0.0`` option. Don't do this when using a reverse proxy setup,
-otherwise it will be possible to bypass the proxy.
-
-.. code-block:: text
-
- $ gunicorn -w 4 -b 0.0.0.0 'hello:create_app()'
- Listening at: http://0.0.0.0:8000 (x)
-
-``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
-IP address in your browser.
-
-
-Async with gevent or eventlet
------------------------------
-
-The default sync worker is appropriate for many use cases. If you need
-asynchronous support, Gunicorn provides workers using either `gevent`_
-or `eventlet`_. This is not the same as Python's ``async/await``, or the
-ASGI server spec. You must actually use gevent/eventlet in your own code
-to see any benefit to using the workers.
-
-When using either gevent or eventlet, greenlet>=1.0 is required,
-otherwise context locals such as ``request`` will not work as expected.
-When using PyPy, PyPy>=7.3.7 is required.
-
-To use gevent:
-
-.. code-block:: text
-
- $ gunicorn -k gevent 'hello:create_app()'
- Starting gunicorn 20.1.0
- Listening at: http://127.0.0.1:8000 (x)
- Using worker: gevent
- Booting worker with pid: x
-
-To use eventlet:
-
-.. code-block:: text
-
- $ gunicorn -k eventlet 'hello:create_app()'
- Starting gunicorn 20.1.0
- Listening at: http://127.0.0.1:8000 (x)
- Using worker: eventlet
- Booting worker with pid: x
-
-.. _gevent: https://www.gevent.org/
-.. _eventlet: https://eventlet.net/
diff --git a/docs/deploying/index.rst b/docs/deploying/index.rst
deleted file mode 100644
index 4135596a..00000000
--- a/docs/deploying/index.rst
+++ /dev/null
@@ -1,79 +0,0 @@
-Deploying to Production
-=======================
-
-After developing your application, you'll want to make it available
-publicly to other users. When you're developing locally, you're probably
-using the built-in development server, debugger, and reloader. These
-should not be used in production. Instead, you should use a dedicated
-WSGI server or hosting platform, some of which will be described here.
-
-"Production" means "not development", which applies whether you're
-serving your application publicly to millions of users or privately /
-locally to a single user. **Do not use the development server when
-deploying to production. It is intended for use only during local
-development. It is not designed to be particularly secure, stable, or
-efficient.**
-
-Self-Hosted Options
--------------------
-
-Flask is a WSGI *application*. A WSGI *server* is used to run the
-application, converting incoming HTTP requests to the standard WSGI
-environ, and converting outgoing WSGI responses to HTTP responses.
-
-The primary goal of these docs is to familiarize you with the concepts
-involved in running a WSGI application using a production WSGI server
-and HTTP server. There are many WSGI servers and HTTP servers, with many
-configuration possibilities. The pages below discuss the most common
-servers, and show the basics of running each one. The next section
-discusses platforms that can manage this for you.
-
-.. toctree::
- :maxdepth: 1
-
- gunicorn
- waitress
- mod_wsgi
- uwsgi
- gevent
- eventlet
- asgi
-
-WSGI servers have HTTP servers built-in. However, a dedicated HTTP
-server may be safer, more efficient, or more capable. Putting an HTTP
-server in front of the WSGI server is called a "reverse proxy."
-
-.. toctree::
- :maxdepth: 1
-
- proxy_fix
- nginx
- apache-httpd
-
-This list is not exhaustive, and you should evaluate these and other
-servers based on your application's needs. Different servers will have
-different capabilities, configuration, and support.
-
-
-Hosting Platforms
------------------
-
-There are many services available for hosting web applications without
-needing to maintain your own server, networking, domain, etc. Some
-services may have a free tier up to a certain time or bandwidth. Many of
-these services use one of the WSGI servers described above, or a similar
-interface. The links below are for some of the most common platforms,
-which have instructions for Flask, WSGI, or Python.
-
-- `PythonAnywhere `_
-- `Google App Engine `_
-- `Google Cloud Run `_
-- `AWS Elastic Beanstalk `_
-- `Microsoft Azure `_
-
-This list is not exhaustive, and you should evaluate these and other
-services based on your application's needs. Different services will have
-different capabilities, configuration, pricing, and support.
-
-You'll probably need to :doc:`proxy_fix` when using most hosting
-platforms.
diff --git a/docs/deploying/mod_wsgi.rst b/docs/deploying/mod_wsgi.rst
deleted file mode 100644
index 23e82279..00000000
--- a/docs/deploying/mod_wsgi.rst
+++ /dev/null
@@ -1,94 +0,0 @@
-mod_wsgi
-========
-
-`mod_wsgi`_ is a WSGI server integrated with the `Apache httpd`_ server.
-The modern `mod_wsgi-express`_ command makes it easy to configure and
-start the server without needing to write Apache httpd configuration.
-
-* Tightly integrated with Apache httpd.
-* Supports Windows directly.
-* Requires a compiler and the Apache development headers to install.
-* Does not require a reverse proxy setup.
-
-This page outlines the basics of running mod_wsgi-express, not the more
-complex installation and configuration with httpd. Be sure to read the
-`mod_wsgi-express`_, `mod_wsgi`_, and `Apache httpd`_ documentation to
-understand what features are available.
-
-.. _mod_wsgi-express: https://pypi.org/project/mod-wsgi/
-.. _mod_wsgi: https://modwsgi.readthedocs.io/
-.. _Apache httpd: https://httpd.apache.org/
-
-
-Installing
-----------
-
-Installing mod_wsgi requires a compiler and the Apache server and
-development headers installed. You will get an error if they are not.
-How to install them depends on the OS and package manager that you use.
-
-Create a virtualenv, install your application, then install
-``mod_wsgi``.
-
-.. code-block:: text
-
- $ cd hello-app
- $ python -m venv .venv
- $ . .venv/bin/activate
- $ pip install . # install your application
- $ pip install mod_wsgi
-
-
-Running
--------
-
-The only argument to ``mod_wsgi-express`` specifies a script containing
-your Flask application, which must be called ``application``. You can
-write a small script to import your app with this name, or to create it
-if using the app factory pattern.
-
-.. code-block:: python
- :caption: ``wsgi.py``
-
- from hello import app
-
- application = app
-
-.. code-block:: python
- :caption: ``wsgi.py``
-
- from hello import create_app
-
- application = create_app()
-
-Now run the ``mod_wsgi-express start-server`` command.
-
-.. code-block:: text
-
- $ mod_wsgi-express start-server wsgi.py --processes 4
-
-The ``--processes`` option specifies the number of worker processes to
-run; a starting value could be ``CPU * 2``.
-
-Logs for each request aren't show in the terminal. If an error occurs,
-its information is written to the error log file shown when starting the
-server.
-
-
-Binding Externally
-------------------
-
-Unlike the other WSGI servers in these docs, mod_wsgi can be run as
-root to bind to privileged ports like 80 and 443. However, it must be
-configured to drop permissions to a different user and group for the
-worker processes.
-
-For example, if you created a ``hello`` user and group, you should
-install your virtualenv and application as that user, then tell
-mod_wsgi to drop to that user after starting.
-
-.. code-block:: text
-
- $ sudo /home/hello/.venv/bin/mod_wsgi-express start-server \
- /home/hello/wsgi.py \
- --user hello --group hello --port 80 --processes 4
diff --git a/docs/deploying/nginx.rst b/docs/deploying/nginx.rst
deleted file mode 100644
index 6b25c073..00000000
--- a/docs/deploying/nginx.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-nginx
-=====
-
-`nginx`_ is a fast, production level HTTP server. When serving your
-application with one of the WSGI servers listed in :doc:`index`, it is
-often good or necessary to put a dedicated HTTP server in front of it.
-This "reverse proxy" can handle incoming requests, TLS, and other
-security and performance concerns better than the WSGI server.
-
-Nginx can be installed using your system package manager, or a pre-built
-executable for Windows. Installing and running Nginx itself is outside
-the scope of this doc. This page outlines the basics of configuring
-Nginx to proxy your application. Be sure to read its documentation to
-understand what features are available.
-
-.. _nginx: https://nginx.org/
-
-
-Domain Name
------------
-
-Acquiring and configuring a domain name is outside the scope of this
-doc. In general, you will buy a domain name from a registrar, pay for
-server space with a hosting provider, and then point your registrar
-at the hosting provider's name servers.
-
-To simulate this, you can also edit your ``hosts`` file, located at
-``/etc/hosts`` on Linux. Add a line that associates a name with the
-local IP.
-
-Modern Linux systems may be configured to treat any domain name that
-ends with ``.localhost`` like this without adding it to the ``hosts``
-file.
-
-.. code-block:: python
- :caption: ``/etc/hosts``
-
- 127.0.0.1 hello.localhost
-
-
-Configuration
--------------
-
-The nginx configuration is located at ``/etc/nginx/nginx.conf`` on
-Linux. It may be different depending on your operating system. Check the
-docs and look for ``nginx.conf``.
-
-Remove or comment out any existing ``server`` section. Add a ``server``
-section and use the ``proxy_pass`` directive to point to the address the
-WSGI server is listening on. We'll assume the WSGI server is listening
-locally at ``http://127.0.0.1:8000``.
-
-.. code-block:: nginx
- :caption: ``/etc/nginx.conf``
-
- server {
- listen 80;
- server_name _;
-
- location / {
- proxy_pass http://127.0.0.1:8000/;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header X-Forwarded-Host $host;
- proxy_set_header X-Forwarded-Prefix /;
- }
- }
-
-Then :doc:`proxy_fix` so that your application uses these headers.
diff --git a/docs/deploying/proxy_fix.rst b/docs/deploying/proxy_fix.rst
deleted file mode 100644
index e2c42e82..00000000
--- a/docs/deploying/proxy_fix.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-Tell Flask it is Behind a Proxy
-===============================
-
-When using a reverse proxy, or many Python hosting platforms, the proxy
-will intercept and forward all external requests to the local WSGI
-server.
-
-From the WSGI server and Flask application's perspectives, requests are
-now coming from the HTTP server to the local address, rather than from
-the remote address to the external server address.
-
-HTTP servers should set ``X-Forwarded-`` headers to pass on the real
-values to the application. The application can then be told to trust and
-use those values by wrapping it with the
-:doc:`werkzeug:middleware/proxy_fix` middleware provided by Werkzeug.
-
-This middleware should only be used if the application is actually
-behind a proxy, and should be configured with the number of proxies that
-are chained in front of it. Not all proxies set all the headers. Since
-incoming headers can be faked, you must set how many proxies are setting
-each header so the middleware knows what to trust.
-
-.. code-block:: python
-
- from werkzeug.middleware.proxy_fix import ProxyFix
-
- app.wsgi_app = ProxyFix(
- app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1
- )
-
-Remember, only apply this middleware if you are behind a proxy, and set
-the correct number of proxies that set each header. It can be a security
-issue if you get this configuration wrong.
diff --git a/docs/deploying/uwsgi.rst b/docs/deploying/uwsgi.rst
deleted file mode 100644
index 1f9d5eca..00000000
--- a/docs/deploying/uwsgi.rst
+++ /dev/null
@@ -1,145 +0,0 @@
-uWSGI
-=====
-
-`uWSGI`_ is a fast, compiled server suite with extensive configuration
-and capabilities beyond a basic server.
-
-* It can be very performant due to being a compiled program.
-* It is complex to configure beyond the basic application, and has so
- many options that it can be difficult for beginners to understand.
-* It does not support Windows (but does run on WSL).
-* It requires a compiler to install in some cases.
-
-This page outlines the basics of running uWSGI. Be sure to read its
-documentation to understand what features are available.
-
-.. _uWSGI: https://uwsgi-docs.readthedocs.io/en/latest/
-
-
-Installing
-----------
-
-uWSGI has multiple ways to install it. The most straightforward is to
-install the ``pyuwsgi`` package, which provides precompiled wheels for
-common platforms. However, it does not provide SSL support, which can be
-provided with a reverse proxy instead.
-
-Create a virtualenv, install your application, then install ``pyuwsgi``.
-
-.. code-block:: text
-
- $ cd hello-app
- $ python -m venv .venv
- $ . .venv/bin/activate
- $ pip install . # install your application
- $ pip install pyuwsgi
-
-If you have a compiler available, you can install the ``uwsgi`` package
-instead. Or install the ``pyuwsgi`` package from sdist instead of wheel.
-Either method will include SSL support.
-
-.. code-block:: text
-
- $ pip install uwsgi
-
- # or
- $ pip install --no-binary pyuwsgi pyuwsgi
-
-
-Running
--------
-
-The most basic way to run uWSGI is to tell it to start an HTTP server
-and import your application.
-
-.. code-block:: text
-
- $ uwsgi --http 127.0.0.1:8000 --master -p 4 -w hello:app
-
- *** Starting uWSGI 2.0.20 (64bit) on [x] ***
- *** Operational MODE: preforking ***
- mounting hello:app on /
- spawned uWSGI master process (pid: x)
- spawned uWSGI worker 1 (pid: x, cores: 1)
- spawned uWSGI worker 2 (pid: x, cores: 1)
- spawned uWSGI worker 3 (pid: x, cores: 1)
- spawned uWSGI worker 4 (pid: x, cores: 1)
- spawned uWSGI http 1 (pid: x)
-
-If you're using the app factory pattern, you'll need to create a small
-Python file to create the app, then point uWSGI at that.
-
-.. code-block:: python
- :caption: ``wsgi.py``
-
- from hello import create_app
-
- app = create_app()
-
-.. code-block:: text
-
- $ uwsgi --http 127.0.0.1:8000 --master -p 4 -w wsgi:app
-
-The ``--http`` option starts an HTTP server at 127.0.0.1 port 8000. The
-``--master`` option specifies the standard worker manager. The ``-p``
-option starts 4 worker processes; a starting value could be ``CPU * 2``.
-The ``-w`` option tells uWSGI how to import your application
-
-
-Binding Externally
-------------------
-
-uWSGI should not be run as root with the configuration shown in this doc
-because it would cause your application code to run as root, which is
-not secure. However, this means it will not be possible to bind to port
-80 or 443. Instead, a reverse proxy such as :doc:`nginx` or
-:doc:`apache-httpd` should be used in front of uWSGI. It is possible to
-run uWSGI as root securely, but that is beyond the scope of this doc.
-
-uWSGI has optimized integration with `Nginx uWSGI`_ and
-`Apache mod_proxy_uwsgi`_, and possibly other servers, instead of using
-a standard HTTP proxy. That configuration is beyond the scope of this
-doc, see the links for more information.
-
-.. _Nginx uWSGI: https://uwsgi-docs.readthedocs.io/en/latest/Nginx.html
-.. _Apache mod_proxy_uwsgi: https://uwsgi-docs.readthedocs.io/en/latest/Apache.html#mod-proxy-uwsgi
-
-You can bind to all external IPs on a non-privileged port using the
-``--http 0.0.0.0:8000`` option. Don't do this when using a reverse proxy
-setup, otherwise it will be possible to bypass the proxy.
-
-.. code-block:: text
-
- $ uwsgi --http 0.0.0.0:8000 --master -p 4 -w wsgi:app
-
-``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
-IP address in your browser.
-
-
-Async with gevent
------------------
-
-The default sync worker is appropriate for many use cases. If you need
-asynchronous support, uWSGI provides a `gevent`_ worker. This is not the
-same as Python's ``async/await``, or the ASGI server spec. You must
-actually use gevent in your own code to see any benefit to using the
-worker.
-
-When using gevent, greenlet>=1.0 is required, otherwise context locals
-such as ``request`` will not work as expected. When using PyPy,
-PyPy>=7.3.7 is required.
-
-.. code-block:: text
-
- $ uwsgi --http 127.0.0.1:8000 --master --gevent 100 -w wsgi:app
-
- *** Starting uWSGI 2.0.20 (64bit) on [x] ***
- *** Operational MODE: async ***
- mounting hello:app on /
- spawned uWSGI master process (pid: x)
- spawned uWSGI worker 1 (pid: x, cores: 100)
- spawned uWSGI http 1 (pid: x)
- *** running gevent loop engine [addr:x] ***
-
-
-.. _gevent: https://www.gevent.org/
diff --git a/docs/deploying/waitress.rst b/docs/deploying/waitress.rst
deleted file mode 100644
index 7bdd695b..00000000
--- a/docs/deploying/waitress.rst
+++ /dev/null
@@ -1,75 +0,0 @@
-Waitress
-========
-
-`Waitress`_ is a pure Python WSGI server.
-
-* It is easy to configure.
-* It supports Windows directly.
-* It is easy to install as it does not require additional dependencies
- or compilation.
-* It does not support streaming requests, full request data is always
- buffered.
-* It uses a single process with multiple thread workers.
-
-This page outlines the basics of running Waitress. Be sure to read its
-documentation and ``waitress-serve --help`` to understand what features
-are available.
-
-.. _Waitress: https://docs.pylonsproject.org/projects/waitress/
-
-
-Installing
-----------
-
-Create a virtualenv, install your application, then install
-``waitress``.
-
-.. code-block:: text
-
- $ cd hello-app
- $ python -m venv .venv
- $ . .venv/bin/activate
- $ pip install . # install your application
- $ pip install waitress
-
-
-Running
--------
-
-The only required argument to ``waitress-serve`` tells it how to load
-your Flask application. The syntax is ``{module}:{app}``. ``module`` is
-the dotted import name to the module with your application. ``app`` is
-the variable with the application. If you're using the app factory
-pattern, use ``--call {module}:{factory}`` instead.
-
-.. code-block:: text
-
- # equivalent to 'from hello import app'
- $ waitress-serve --host 127.0.0.1 hello:app
-
- # equivalent to 'from hello import create_app; create_app()'
- $ waitress-serve --host 127.0.0.1 --call hello:create_app
-
- Serving on http://127.0.0.1:8080
-
-The ``--host`` option binds the server to local ``127.0.0.1`` only.
-
-Logs for each request aren't shown, only errors are shown. Logging can
-be configured through the Python interface instead of the command line.
-
-
-Binding Externally
-------------------
-
-Waitress should not be run as root because it would cause your
-application code to run as root, which is not secure. However, this
-means it will not be possible to bind to port 80 or 443. Instead, a
-reverse proxy such as :doc:`nginx` or :doc:`apache-httpd` should be used
-in front of Waitress.
-
-You can bind to all external IPs on a non-privileged port by not
-specifying the ``--host`` option. Don't do this when using a reverse
-proxy setup, otherwise it will be possible to bypass the proxy.
-
-``0.0.0.0`` is not a valid address to navigate to, you'd use a specific
-IP address in your browser.
diff --git a/docs/design.rst b/docs/design.rst
deleted file mode 100644
index 066cf107..00000000
--- a/docs/design.rst
+++ /dev/null
@@ -1,228 +0,0 @@
-Design Decisions in Flask
-=========================
-
-If you are curious why Flask does certain things the way it does and not
-differently, this section is for you. This should give you an idea about
-some of the design decisions that may appear arbitrary and surprising at
-first, especially in direct comparison with other frameworks.
-
-
-The Explicit Application Object
--------------------------------
-
-A Python web application based on WSGI has to have one central callable
-object that implements the actual application. In Flask this is an
-instance of the :class:`~flask.Flask` class. Each Flask application has
-to create an instance of this class itself and pass it the name of the
-module, but why can't Flask do that itself?
-
-Without such an explicit application object the following code::
-
- from flask import Flask
- app = Flask(__name__)
-
- @app.route('/')
- def index():
- return 'Hello World!'
-
-Would look like this instead::
-
- from hypothetical_flask import route
-
- @route('/')
- def index():
- return 'Hello World!'
-
-There are three major reasons for this. The most important one is that
-implicit application objects require that there may only be one instance at
-the time. There are ways to fake multiple applications with a single
-application object, like maintaining a stack of applications, but this
-causes some problems I won't outline here in detail. Now the question is:
-when does a microframework need more than one application at the same
-time? A good example for this is unit testing. When you want to test
-something it can be very helpful to create a minimal application to test
-specific behavior. When the application object is deleted everything it
-allocated will be freed again.
-
-Another thing that becomes possible when you have an explicit object lying
-around in your code is that you can subclass the base class
-(:class:`~flask.Flask`) to alter specific behavior. This would not be
-possible without hacks if the object were created ahead of time for you
-based on a class that is not exposed to you.
-
-But there is another very important reason why Flask depends on an
-explicit instantiation of that class: the package name. Whenever you
-create a Flask instance you usually pass it `__name__` as package name.
-Flask depends on that information to properly load resources relative
-to your module. With Python's outstanding support for reflection it can
-then access the package to figure out where the templates and static files
-are stored (see :meth:`~flask.Flask.open_resource`). Now obviously there
-are frameworks around that do not need any configuration and will still be
-able to load templates relative to your application module. But they have
-to use the current working directory for that, which is a very unreliable
-way to determine where the application is. The current working directory
-is process-wide and if you are running multiple applications in one
-process (which could happen in a webserver without you knowing) the paths
-will be off. Worse: many webservers do not set the working directory to
-the directory of your application but to the document root which does not
-have to be the same folder.
-
-The third reason is "explicit is better than implicit". That object is
-your WSGI application, you don't have to remember anything else. If you
-want to apply a WSGI middleware, just wrap it and you're done (though
-there are better ways to do that so that you do not lose the reference
-to the application object :meth:`~flask.Flask.wsgi_app`).
-
-Furthermore this design makes it possible to use a factory function to
-create the application which is very helpful for unit testing and similar
-things (:doc:`/patterns/appfactories`).
-
-The Routing System
-------------------
-
-Flask uses the Werkzeug routing system which was designed to
-automatically order routes by complexity. This means that you can declare
-routes in arbitrary order and they will still work as expected. This is a
-requirement if you want to properly implement decorator based routing
-since decorators could be fired in undefined order when the application is
-split into multiple modules.
-
-Another design decision with the Werkzeug routing system is that routes
-in Werkzeug try to ensure that URLs are unique. Werkzeug will go quite far
-with that in that it will automatically redirect to a canonical URL if a route
-is ambiguous.
-
-
-One Template Engine
--------------------
-
-Flask decides on one template engine: Jinja2. Why doesn't Flask have a
-pluggable template engine interface? You can obviously use a different
-template engine, but Flask will still configure Jinja2 for you. While
-that limitation that Jinja2 is *always* configured will probably go away,
-the decision to bundle one template engine and use that will not.
-
-Template engines are like programming languages and each of those engines
-has a certain understanding about how things work. On the surface they
-all work the same: you tell the engine to evaluate a template with a set
-of variables and take the return value as string.
-
-But that's about where similarities end. Jinja2 for example has an
-extensive filter system, a certain way to do template inheritance,
-support for reusable blocks (macros) that can be used from inside
-templates and also from Python code, supports iterative template
-rendering, configurable syntax and more. On the other hand an engine
-like Genshi is based on XML stream evaluation, template inheritance by
-taking the availability of XPath into account and more. Mako on the
-other hand treats templates similar to Python modules.
-
-When it comes to connecting a template engine with an application or
-framework there is more than just rendering templates. For instance,
-Flask uses Jinja2's extensive autoescaping support. Also it provides
-ways to access macros from Jinja2 templates.
-
-A template abstraction layer that would not take the unique features of
-the template engines away is a science on its own and a too large
-undertaking for a microframework like Flask.
-
-Furthermore extensions can then easily depend on one template language
-being present. You can easily use your own templating language, but an
-extension could still depend on Jinja itself.
-
-
-What does "micro" mean?
------------------------
-
-“Micro” does not mean that your whole web application has to fit into a single
-Python file (although it certainly can), nor does it mean that Flask is lacking
-in functionality. The "micro" in microframework means Flask aims to keep the
-core simple but extensible. Flask won't make many decisions for you, such as
-what database to use. Those decisions that it does make, such as what
-templating engine to use, are easy to change. Everything else is up to you, so
-that Flask can be everything you need and nothing you don't.
-
-By default, Flask does not include a database abstraction layer, form
-validation or anything else where different libraries already exist that can
-handle that. Instead, Flask supports extensions to add such functionality to
-your application as if it was implemented in Flask itself. Numerous extensions
-provide database integration, form validation, upload handling, various open
-authentication technologies, and more. Flask may be "micro", but it's ready for
-production use on a variety of needs.
-
-Why does Flask call itself a microframework and yet it depends on two
-libraries (namely Werkzeug and Jinja2). Why shouldn't it? If we look
-over to the Ruby side of web development there we have a protocol very
-similar to WSGI. Just that it's called Rack there, but besides that it
-looks very much like a WSGI rendition for Ruby. But nearly all
-applications in Ruby land do not work with Rack directly, but on top of a
-library with the same name. This Rack library has two equivalents in
-Python: WebOb (formerly Paste) and Werkzeug. Paste is still around but
-from my understanding it's sort of deprecated in favour of WebOb. The
-development of WebOb and Werkzeug started side by side with similar ideas
-in mind: be a good implementation of WSGI for other applications to take
-advantage.
-
-Flask is a framework that takes advantage of the work already done by
-Werkzeug to properly interface WSGI (which can be a complex task at
-times). Thanks to recent developments in the Python package
-infrastructure, packages with dependencies are no longer an issue and
-there are very few reasons against having libraries that depend on others.
-
-
-Thread Locals
--------------
-
-Flask uses thread local objects (context local objects in fact, they
-support greenlet contexts as well) for request, session and an extra
-object you can put your own things on (:data:`~flask.g`). Why is that and
-isn't that a bad idea?
-
-Yes it is usually not such a bright idea to use thread locals. They cause
-troubles for servers that are not based on the concept of threads and make
-large applications harder to maintain. However Flask is just not designed
-for large applications or asynchronous servers. Flask wants to make it
-quick and easy to write a traditional web application.
-
-
-Async/await and ASGI support
-----------------------------
-
-Flask supports ``async`` coroutines for view functions by executing the
-coroutine on a separate thread instead of using an event loop on the
-main thread as an async-first (ASGI) framework would. This is necessary
-for Flask to remain backwards compatible with extensions and code built
-before ``async`` was introduced into Python. This compromise introduces
-a performance cost compared with the ASGI frameworks, due to the
-overhead of the threads.
-
-Due to how tied to WSGI Flask's code is, it's not clear if it's possible
-to make the ``Flask`` class support ASGI and WSGI at the same time. Work
-is currently being done in Werkzeug to work with ASGI, which may
-eventually enable support in Flask as well.
-
-See :doc:`/async-await` for more discussion.
-
-
-What Flask is, What Flask is Not
---------------------------------
-
-Flask will never have a database layer. It will not have a form library
-or anything else in that direction. Flask itself just bridges to Werkzeug
-to implement a proper WSGI application and to Jinja2 to handle templating.
-It also binds to a few common standard library packages such as logging.
-Everything else is up for extensions.
-
-Why is this the case? Because people have different preferences and
-requirements and Flask could not meet those if it would force any of this
-into the core. The majority of web applications will need a template
-engine in some sort. However not every application needs a SQL database.
-
-As your codebase grows, you are free to make the design decisions appropriate
-for your project. Flask will continue to provide a very simple glue layer to
-the best that Python has to offer. You can implement advanced patterns in
-SQLAlchemy or another database tool, introduce non-relational data persistence
-as appropriate, and take advantage of framework-agnostic tools built for WSGI,
-the Python web interface.
-
-The idea of Flask is to build a good foundation for all applications.
-Everything else is up to you or extensions.
diff --git a/docs/errorhandling.rst b/docs/errorhandling.rst
deleted file mode 100644
index faca58c2..00000000
--- a/docs/errorhandling.rst
+++ /dev/null
@@ -1,523 +0,0 @@
-Handling Application Errors
-===========================
-
-Applications fail, servers fail. Sooner or later you will see an exception
-in production. Even if your code is 100% correct, you will still see
-exceptions from time to time. Why? Because everything else involved will
-fail. Here are some situations where perfectly fine code can lead to server
-errors:
-
-- the client terminated the request early and the application was still
- reading from the incoming data
-- the database server was overloaded and could not handle the query
-- a filesystem is full
-- a harddrive crashed
-- a backend server overloaded
-- a programming error in a library you are using
-- network connection of the server to another system failed
-
-And that's just a small sample of issues you could be facing. So how do we
-deal with that sort of problem? By default if your application runs in
-production mode, and an exception is raised Flask will display a very simple
-page for you and log the exception to the :attr:`~flask.Flask.logger`.
-
-But there is more you can do, and we will cover some better setups to deal
-with errors including custom exceptions and 3rd party tools.
-
-
-.. _error-logging-tools:
-
-Error Logging Tools
--------------------
-
-Sending error mails, even if just for critical ones, can become
-overwhelming if enough users are hitting the error and log files are
-typically never looked at. This is why we recommend using `Sentry
-`_ for dealing with application errors. It's
-available as a source-available project `on GitHub
-`_ and is also available as a `hosted version
-`_ which you can try for free. Sentry
-aggregates duplicate errors, captures the full stack trace and local
-variables for debugging, and sends you mails based on new errors or
-frequency thresholds.
-
-To use Sentry you need to install the ``sentry-sdk`` client with extra
-``flask`` dependencies.
-
-.. code-block:: text
-
- $ pip install sentry-sdk[flask]
-
-And then add this to your Flask app:
-
-.. code-block:: python
-
- import sentry_sdk
- from sentry_sdk.integrations.flask import FlaskIntegration
-
- sentry_sdk.init('YOUR_DSN_HERE', integrations=[FlaskIntegration()])
-
-The ``YOUR_DSN_HERE`` value needs to be replaced with the DSN value you
-get from your Sentry installation.
-
-After installation, failures leading to an Internal Server Error
-are automatically reported to Sentry and from there you can
-receive error notifications.
-
-See also:
-
-- Sentry also supports catching errors from a worker queue
- (RQ, Celery, etc.) in a similar fashion. See the `Python SDK docs
- `__ for more information.
-- `Flask-specific documentation `__
-
-
-Error Handlers
---------------
-
-When an error occurs in Flask, an appropriate `HTTP status code
-`__ will be
-returned. 400-499 indicate errors with the client's request data, or
-about the data requested. 500-599 indicate errors with the server or
-application itself.
-
-You might want to show custom error pages to the user when an error occurs.
-This can be done by registering error handlers.
-
-An error handler is a function that returns a response when a type of error is
-raised, similar to how a view is a function that returns a response when a
-request URL is matched. It is passed the instance of the error being handled,
-which is most likely a :exc:`~werkzeug.exceptions.HTTPException`.
-
-The status code of the response will not be set to the handler's code. Make
-sure to provide the appropriate HTTP status code when returning a response from
-a handler.
-
-
-Registering
-```````````
-
-Register handlers by decorating a function with
-:meth:`~flask.Flask.errorhandler`. Or use
-:meth:`~flask.Flask.register_error_handler` to register the function later.
-Remember to set the error code when returning the response.
-
-.. code-block:: python
-
- @app.errorhandler(werkzeug.exceptions.BadRequest)
- def handle_bad_request(e):
- return 'bad request!', 400
-
- # or, without the decorator
- app.register_error_handler(400, handle_bad_request)
-
-:exc:`werkzeug.exceptions.HTTPException` subclasses like
-:exc:`~werkzeug.exceptions.BadRequest` and their HTTP codes are interchangeable
-when registering handlers. (``BadRequest.code == 400``)
-
-Non-standard HTTP codes cannot be registered by code because they are not known
-by Werkzeug. Instead, define a subclass of
-:class:`~werkzeug.exceptions.HTTPException` with the appropriate code and
-register and raise that exception class.
-
-.. code-block:: python
-
- class InsufficientStorage(werkzeug.exceptions.HTTPException):
- code = 507
- description = 'Not enough storage space.'
-
- app.register_error_handler(InsufficientStorage, handle_507)
-
- raise InsufficientStorage()
-
-Handlers can be registered for any exception class, not just
-:exc:`~werkzeug.exceptions.HTTPException` subclasses or HTTP status
-codes. Handlers can be registered for a specific class, or for all subclasses
-of a parent class.
-
-
-Handling
-````````
-
-When building a Flask application you *will* run into exceptions. If some part
-of your code breaks while handling a request (and you have no error handlers
-registered), a "500 Internal Server Error"
-(:exc:`~werkzeug.exceptions.InternalServerError`) will be returned by default.
-Similarly, "404 Not Found"
-(:exc:`~werkzeug.exceptions.NotFound`) error will occur if a request is sent to an unregistered route.
-If a route receives an unallowed request method, a "405 Method Not Allowed"
-(:exc:`~werkzeug.exceptions.MethodNotAllowed`) will be raised. These are all
-subclasses of :class:`~werkzeug.exceptions.HTTPException` and are provided by
-default in Flask.
-
-Flask gives you the ability to raise any HTTP exception registered by
-Werkzeug. However, the default HTTP exceptions return simple exception
-pages. You might want to show custom error pages to the user when an error occurs.
-This can be done by registering error handlers.
-
-When Flask catches an exception while handling a request, it is first looked up by code.
-If no handler is registered for the code, Flask looks up the error by its class hierarchy; the most specific handler is chosen.
-If no handler is registered, :class:`~werkzeug.exceptions.HTTPException` subclasses show a
-generic message about their code, while other exceptions are converted to a
-generic "500 Internal Server Error".
-
-For example, if an instance of :exc:`ConnectionRefusedError` is raised,
-and a handler is registered for :exc:`ConnectionError` and
-:exc:`ConnectionRefusedError`, the more specific :exc:`ConnectionRefusedError`
-handler is called with the exception instance to generate the response.
-
-Handlers registered on the blueprint take precedence over those registered
-globally on the application, assuming a blueprint is handling the request that
-raises the exception. However, the blueprint cannot handle 404 routing errors
-because the 404 occurs at the routing level before the blueprint can be
-determined.
-
-
-Generic Exception Handlers
-``````````````````````````
-
-It is possible to register error handlers for very generic base classes
-such as ``HTTPException`` or even ``Exception``. However, be aware that
-these will catch more than you might expect.
-
-For example, an error handler for ``HTTPException`` might be useful for turning
-the default HTML errors pages into JSON. However, this
-handler will trigger for things you don't cause directly, such as 404
-and 405 errors during routing. Be sure to craft your handler carefully
-so you don't lose information about the HTTP error.
-
-.. code-block:: python
-
- from flask import json
- from werkzeug.exceptions import HTTPException
-
- @app.errorhandler(HTTPException)
- def handle_exception(e):
- """Return JSON instead of HTML for HTTP errors."""
- # start with the correct headers and status code from the error
- response = e.get_response()
- # replace the body with JSON
- response.data = json.dumps({
- "code": e.code,
- "name": e.name,
- "description": e.description,
- })
- response.content_type = "application/json"
- return response
-
-An error handler for ``Exception`` might seem useful for changing how
-all errors, even unhandled ones, are presented to the user. However,
-this is similar to doing ``except Exception:`` in Python, it will
-capture *all* otherwise unhandled errors, including all HTTP status
-codes.
-
-In most cases it will be safer to register handlers for more
-specific exceptions. Since ``HTTPException`` instances are valid WSGI
-responses, you could also pass them through directly.
-
-.. code-block:: python
-
- from werkzeug.exceptions import HTTPException
-
- @app.errorhandler(Exception)
- def handle_exception(e):
- # pass through HTTP errors
- if isinstance(e, HTTPException):
- return e
-
- # now you're handling non-HTTP exceptions only
- return render_template("500_generic.html", e=e), 500
-
-Error handlers still respect the exception class hierarchy. If you
-register handlers for both ``HTTPException`` and ``Exception``, the
-``Exception`` handler will not handle ``HTTPException`` subclasses
-because the ``HTTPException`` handler is more specific.
-
-
-Unhandled Exceptions
-````````````````````
-
-When there is no error handler registered for an exception, a 500
-Internal Server Error will be returned instead. See
-:meth:`flask.Flask.handle_exception` for information about this
-behavior.
-
-If there is an error handler registered for ``InternalServerError``,
-this will be invoked. As of Flask 1.1.0, this error handler will always
-be passed an instance of ``InternalServerError``, not the original
-unhandled error.
-
-The original error is available as ``e.original_exception``.
-
-An error handler for "500 Internal Server Error" will be passed uncaught
-exceptions in addition to explicit 500 errors. In debug mode, a handler
-for "500 Internal Server Error" will not be used. Instead, the
-interactive debugger will be shown.
-
-
-Custom Error Pages
-------------------
-
-Sometimes when building a Flask application, you might want to raise a
-:exc:`~werkzeug.exceptions.HTTPException` to signal to the user that
-something is wrong with the request. Fortunately, Flask comes with a handy
-:func:`~flask.abort` function that aborts a request with a HTTP error from
-werkzeug as desired. It will also provide a plain black and white error page
-for you with a basic description, but nothing fancy.
-
-Depending on the error code it is less or more likely for the user to
-actually see such an error.
-
-Consider the code below, we might have a user profile route, and if the user
-fails to pass a username we can raise a "400 Bad Request". If the user passes a
-username and we can't find it, we raise a "404 Not Found".
-
-.. code-block:: python
-
- from flask import abort, render_template, request
-
- # a username needs to be supplied in the query args
- # a successful request would be like /profile?username=jack
- @app.route("/profile")
- def user_profile():
- username = request.arg.get("username")
- # if a username isn't supplied in the request, return a 400 bad request
- if username is None:
- abort(400)
-
- user = get_user(username=username)
- # if a user can't be found by their username, return 404 not found
- if user is None:
- abort(404)
-
- return render_template("profile.html", user=user)
-
-Here is another example implementation for a "404 Page Not Found" exception:
-
-.. code-block:: python
-
- from flask import render_template
-
- @app.errorhandler(404)
- def page_not_found(e):
- # note that we set the 404 status explicitly
- return render_template('404.html'), 404
-
-When using :doc:`/patterns/appfactories`:
-
-.. code-block:: python
-
- from flask import Flask, render_template
-
- def page_not_found(e):
- return render_template('404.html'), 404
-
- def create_app(config_filename):
- app = Flask(__name__)
- app.register_error_handler(404, page_not_found)
- return app
-
-An example template might be this:
-
-.. code-block:: html+jinja
-
- {% extends "layout.html" %}
- {% block title %}Page Not Found{% endblock %}
- {% block body %}
-
Page Not Found
-
What you were looking for is just not there.
-
go somewhere nice
- {% endblock %}
-
-
-Further Examples
-````````````````
-
-The above examples wouldn't actually be an improvement on the default
-exception pages. We can create a custom 500.html template like this:
-
-.. code-block:: html+jinja
-
- {% extends "layout.html" %}
- {% block title %}Internal Server Error{% endblock %}
- {% block body %}
-
Internal Server Error
-
Oops... we seem to have made a mistake, sorry!
-
Go somewhere nice instead
- {% endblock %}
-
-It can be implemented by rendering the template on "500 Internal Server Error":
-
-.. code-block:: python
-
- from flask import render_template
-
- @app.errorhandler(500)
- def internal_server_error(e):
- # note that we set the 500 status explicitly
- return render_template('500.html'), 500
-
-When using :doc:`/patterns/appfactories`:
-
-.. code-block:: python
-
- from flask import Flask, render_template
-
- def internal_server_error(e):
- return render_template('500.html'), 500
-
- def create_app():
- app = Flask(__name__)
- app.register_error_handler(500, internal_server_error)
- return app
-
-When using :doc:`/blueprints`:
-
-.. code-block:: python
-
- from flask import Blueprint
-
- blog = Blueprint('blog', __name__)
-
- # as a decorator
- @blog.errorhandler(500)
- def internal_server_error(e):
- return render_template('500.html'), 500
-
- # or with register_error_handler
- blog.register_error_handler(500, internal_server_error)
-
-
-Blueprint Error Handlers
-------------------------
-
-In :doc:`/blueprints`, most error handlers will work as expected.
-However, there is a caveat concerning handlers for 404 and 405
-exceptions. These error handlers are only invoked from an appropriate
-``raise`` statement or a call to ``abort`` in another of the blueprint's
-view functions; they are not invoked by, e.g., an invalid URL access.
-
-This is because the blueprint does not "own" a certain URL space, so
-the application instance has no way of knowing which blueprint error
-handler it should run if given an invalid URL. If you would like to
-execute different handling strategies for these errors based on URL
-prefixes, they may be defined at the application level using the
-``request`` proxy object.
-
-.. code-block:: python
-
- from flask import jsonify, render_template
-
- # at the application level
- # not the blueprint level
- @app.errorhandler(404)
- def page_not_found(e):
- # if a request is in our blog URL space
- if request.path.startswith('/blog/'):
- # we return a custom blog 404 page
- return render_template("blog/404.html"), 404
- else:
- # otherwise we return our generic site-wide 404 page
- return render_template("404.html"), 404
-
- @app.errorhandler(405)
- def method_not_allowed(e):
- # if a request has the wrong method to our API
- if request.path.startswith('/api/'):
- # we return a json saying so
- return jsonify(message="Method Not Allowed"), 405
- else:
- # otherwise we return a generic site-wide 405 page
- return render_template("405.html"), 405
-
-
-Returning API Errors as JSON
-----------------------------
-
-When building APIs in Flask, some developers realise that the built-in
-exceptions are not expressive enough for APIs and that the content type of
-:mimetype:`text/html` they are emitting is not very useful for API consumers.
-
-Using the same techniques as above and :func:`~flask.json.jsonify` we can return JSON
-responses to API errors. :func:`~flask.abort` is called
-with a ``description`` parameter. The error handler will
-use that as the JSON error message, and set the status code to 404.
-
-.. code-block:: python
-
- from flask import abort, jsonify
-
- @app.errorhandler(404)
- def resource_not_found(e):
- return jsonify(error=str(e)), 404
-
- @app.route("/cheese")
- def get_one_cheese():
- resource = get_resource()
-
- if resource is None:
- abort(404, description="Resource not found")
-
- return jsonify(resource)
-
-We can also create custom exception classes. For instance, we can
-introduce a new custom exception for an API that can take a proper human readable message,
-a status code for the error and some optional payload to give more context
-for the error.
-
-This is a simple example:
-
-.. code-block:: python
-
- from flask import jsonify, request
-
- class InvalidAPIUsage(Exception):
- status_code = 400
-
- def __init__(self, message, status_code=None, payload=None):
- super().__init__()
- self.message = message
- if status_code is not None:
- self.status_code = status_code
- self.payload = payload
-
- def to_dict(self):
- rv = dict(self.payload or ())
- rv['message'] = self.message
- return rv
-
- @app.errorhandler(InvalidAPIUsage)
- def invalid_api_usage(e):
- return jsonify(e.to_dict()), e.status_code
-
- # an API app route for getting user information
- # a correct request might be /api/user?user_id=420
- @app.route("/api/user")
- def user_api(user_id):
- user_id = request.arg.get("user_id")
- if not user_id:
- raise InvalidAPIUsage("No user id provided!")
-
- user = get_user(user_id=user_id)
- if not user:
- raise InvalidAPIUsage("No such user!", status_code=404)
-
- return jsonify(user.to_dict())
-
-A view can now raise that exception with an error message. Additionally
-some extra payload can be provided as a dictionary through the `payload`
-parameter.
-
-
-Logging
--------
-
-See :doc:`/logging` for information about how to log exceptions, such as
-by emailing them to admins.
-
-
-Debugging
----------
-
-See :doc:`/debugging` for information about how to debug errors in
-development and production.
diff --git a/docs/extensiondev.rst b/docs/extensiondev.rst
deleted file mode 100644
index 0c74ad92..00000000
--- a/docs/extensiondev.rst
+++ /dev/null
@@ -1,304 +0,0 @@
-Flask Extension Development
-===========================
-
-.. currentmodule:: flask
-
-Extensions are extra packages that add functionality to a Flask
-application. While `PyPI`_ contains many Flask extensions, you may not
-find one that fits your need. If this is the case, you can create your
-own, and publish it for others to use as well.
-
-This guide will show how to create a Flask extension, and some of the
-common patterns and requirements involved. Since extensions can do
-anything, this guide won't be able to cover every possibility.
-
-The best ways to learn about extensions are to look at how other
-extensions you use are written, and discuss with others. Discuss your
-design ideas with others on our `Discord Chat`_ or
-`GitHub Discussions`_.
-
-The best extensions share common patterns, so that anyone familiar with
-using one extension won't feel completely lost with another. This can
-only work if collaboration happens early.
-
-
-Naming
-------
-
-A Flask extension typically has ``flask`` in its name as a prefix or
-suffix. If it wraps another library, it should include the library name
-as well. This makes it easy to search for extensions, and makes their
-purpose clearer.
-
-A general Python packaging recommendation is that the install name from
-the package index and the name used in ``import`` statements should be
-related. The import name is lowercase, with words separated by
-underscores (``_``). The install name is either lower case or title
-case, with words separated by dashes (``-``). If it wraps another
-library, prefer using the same case as that library's name.
-
-Here are some example install and import names:
-
-- ``Flask-Name`` imported as ``flask_name``
-- ``flask-name-lower`` imported as ``flask_name_lower``
-- ``Flask-ComboName`` imported as ``flask_comboname``
-- ``Name-Flask`` imported as ``name_flask``
-
-
-The Extension Class and Initialization
---------------------------------------
-
-All extensions will need some entry point that initializes the
-extension with the application. The most common pattern is to create a
-class that represents the extension's configuration and behavior, with
-an ``init_app`` method to apply the extension instance to the given
-application instance.
-
-.. code-block:: python
-
- class HelloExtension:
- def __init__(self, app=None):
- if app is not None:
- self.init_app(app)
-
- def init_app(self, app):
- app.before_request(...)
-
-It is important that the app is not stored on the extension, don't do
-``self.app = app``. The only time the extension should have direct
-access to an app is during ``init_app``, otherwise it should use
-:data:`current_app`.
-
-This allows the extension to support the application factory pattern,
-avoids circular import issues when importing the extension instance
-elsewhere in a user's code, and makes testing with different
-configurations easier.
-
-.. code-block:: python
-
- hello = HelloExtension()
-
- def create_app():
- app = Flask(__name__)
- hello.init_app(app)
- return app
-
-Above, the ``hello`` extension instance exists independently of the
-application. This means that other modules in a user's project can do
-``from project import hello`` and use the extension in blueprints before
-the app exists.
-
-The :attr:`Flask.extensions` dict can be used to store a reference to
-the extension on the application, or some other state specific to the
-application. Be aware that this is a single namespace, so use a name
-unique to your extension, such as the extension's name without the
-"flask" prefix.
-
-
-Adding Behavior
----------------
-
-There are many ways that an extension can add behavior. Any setup
-methods that are available on the :class:`Flask` object can be used
-during an extension's ``init_app`` method.
-
-A common pattern is to use :meth:`~Flask.before_request` to initialize
-some data or a connection at the beginning of each request, then
-:meth:`~Flask.teardown_request` to clean it up at the end. This can be
-stored on :data:`g`, discussed more below.
-
-A more lazy approach is to provide a method that initializes and caches
-the data or connection. For example, a ``ext.get_db`` method could
-create a database connection the first time it's called, so that a view
-that doesn't use the database doesn't create a connection.
-
-Besides doing something before and after every view, your extension
-might want to add some specific views as well. In this case, you could
-define a :class:`Blueprint`, then call :meth:`~Flask.register_blueprint`
-during ``init_app`` to add the blueprint to the app.
-
-
-Configuration Techniques
-------------------------
-
-There can be multiple levels and sources of configuration for an
-extension. You should consider what parts of your extension fall into
-each one.
-
-- Configuration per application instance, through ``app.config``
- values. This is configuration that could reasonably change for each
- deployment of an application. A common example is a URL to an
- external resource, such as a database. Configuration keys should
- start with the extension's name so that they don't interfere with
- other extensions.
-- Configuration per extension instance, through ``__init__``
- arguments. This configuration usually affects how the extension
- is used, such that it wouldn't make sense to change it per
- deployment.
-- Configuration per extension instance, through instance attributes
- and decorator methods. It might be more ergonomic to assign to
- ``ext.value``, or use a ``@ext.register`` decorator to register a
- function, after the extension instance has been created.
-- Global configuration through class attributes. Changing a class
- attribute like ``Ext.connection_class`` can customize default
- behavior without making a subclass. This could be combined
- per-extension configuration to override defaults.
-- Subclassing and overriding methods and attributes. Making the API of
- the extension itself something that can be overridden provides a
- very powerful tool for advanced customization.
-
-The :class:`~flask.Flask` object itself uses all of these techniques.
-
-It's up to you to decide what configuration is appropriate for your
-extension, based on what you need and what you want to support.
-
-Configuration should not be changed after the application setup phase is
-complete and the server begins handling requests. Configuration is
-global, any changes to it are not guaranteed to be visible to other
-workers.
-
-
-Data During a Request
----------------------
-
-When writing a Flask application, the :data:`~flask.g` object is used to
-store information during a request. For example the
-:doc:`tutorial ` stores a connection to a SQLite
-database as ``g.db``. Extensions can also use this, with some care.
-Since ``g`` is a single global namespace, extensions must use unique
-names that won't collide with user data. For example, use the extension
-name as a prefix, or as a namespace.
-
-.. code-block:: python
-
- # an internal prefix with the extension name
- g._hello_user_id = 2
-
- # or an internal prefix as a namespace
- from types import SimpleNamespace
- g._hello = SimpleNamespace()
- g._hello.user_id = 2
-
-The data in ``g`` lasts for an application context. An application
-context is active when a request context is, or when a CLI command is
-run. If you're storing something that should be closed, use
-:meth:`~flask.Flask.teardown_appcontext` to ensure that it gets closed
-when the application context ends. If it should only be valid during a
-request, or would not be used in the CLI outside a request, use
-:meth:`~flask.Flask.teardown_request`.
-
-
-Views and Models
-----------------
-
-Your extension views might want to interact with specific models in your
-database, or some other extension or data connected to your application.
-For example, let's consider a ``Flask-SimpleBlog`` extension that works
-with Flask-SQLAlchemy to provide a ``Post`` model and views to write
-and read posts.
-
-The ``Post`` model needs to subclass the Flask-SQLAlchemy ``db.Model``
-object, but that's only available once you've created an instance of
-that extension, not when your extension is defining its views. So how
-can the view code, defined before the model exists, access the model?
-
-One method could be to use :doc:`views`. During ``__init__``, create
-the model, then create the views by passing the model to the view
-class's :meth:`~views.View.as_view` method.
-
-.. code-block:: python
-
- class PostAPI(MethodView):
- def __init__(self, model):
- self.model = model
-
- def get(self, id):
- post = self.model.query.get(id)
- return jsonify(post.to_json())
-
- class BlogExtension:
- def __init__(self, db):
- class Post(db.Model):
- id = db.Column(primary_key=True)
- title = db.Column(db.String, nullable=False)
-
- self.post_model = Post
-
- def init_app(self, app):
- api_view = PostAPI.as_view(model=self.post_model)
-
- db = SQLAlchemy()
- blog = BlogExtension(db)
- db.init_app(app)
- blog.init_app(app)
-
-Another technique could be to use an attribute on the extension, such as
-``self.post_model`` from above. Add the extension to ``app.extensions``
-in ``init_app``, then access
-``current_app.extensions["simple_blog"].post_model`` from views.
-
-You may also want to provide base classes so that users can provide
-their own ``Post`` model that conforms to the API your extension
-expects. So they could implement ``class Post(blog.BasePost)``, then
-set it as ``blog.post_model``.
-
-As you can see, this can get a bit complex. Unfortunately, there's no
-perfect solution here, only different strategies and tradeoffs depending
-on your needs and how much customization you want to offer. Luckily,
-this sort of resource dependency is not a common need for most
-extensions. Remember, if you need help with design, ask on our
-`Discord Chat`_ or `GitHub Discussions`_.
-
-
-Recommended Extension Guidelines
---------------------------------
-
-Flask previously had the concept of "approved extensions", where the
-Flask maintainers evaluated the quality, support, and compatibility of
-the extensions before listing them. While the list became too difficult
-to maintain over time, the guidelines are still relevant to all
-extensions maintained and developed today, as they help the Flask
-ecosystem remain consistent and compatible.
-
-1. An extension requires a maintainer. In the event an extension author
- would like to move beyond the project, the project should find a new
- maintainer and transfer access to the repository, documentation,
- PyPI, and any other services. The `Pallets-Eco`_ organization on
- GitHub allows for community maintenance with oversight from the
- Pallets maintainers.
-2. The naming scheme is *Flask-ExtensionName* or *ExtensionName-Flask*.
- It must provide exactly one package or module named
- ``flask_extension_name``.
-3. The extension must use an open source license. The Python web
- ecosystem tends to prefer BSD or MIT. It must be open source and
- publicly available.
-4. The extension's API must have the following characteristics:
-
- - It must support multiple applications running in the same Python
- process. Use ``current_app`` instead of ``self.app``, store
- configuration and state per application instance.
- - It must be possible to use the factory pattern for creating
- applications. Use the ``ext.init_app()`` pattern.
-
-5. From a clone of the repository, an extension with its dependencies
- must be installable in editable mode with ``pip install -e .``.
-6. It must ship tests that can be invoked with a common tool like
- ``tox -e py``, ``nox -s test`` or ``pytest``. If not using ``tox``,
- the test dependencies should be specified in a requirements file.
- The tests must be part of the sdist distribution.
-7. A link to the documentation or project website must be in the PyPI
- metadata or the readme. The documentation should use the Flask theme
- from the `Official Pallets Themes`_.
-8. The extension's dependencies should not use upper bounds or assume
- any particular version scheme, but should use lower bounds to
- indicate minimum compatibility support. For example,
- ``sqlalchemy>=1.4``.
-9. Indicate the versions of Python supported using ``python_requires=">=version"``.
- Flask itself supports Python >=3.9 as of October 2024, and this will update
- over time.
-
-.. _PyPI: https://pypi.org/search/?c=Framework+%3A%3A+Flask
-.. _Discord Chat: https://discord.gg/pallets
-.. _GitHub Discussions: https://github.com/pallets/flask/discussions
-.. _Official Pallets Themes: https://pypi.org/project/Pallets-Sphinx-Themes/
-.. _Pallets-Eco: https://github.com/pallets-eco
diff --git a/docs/extensions.rst b/docs/extensions.rst
deleted file mode 100644
index 4713ec8e..00000000
--- a/docs/extensions.rst
+++ /dev/null
@@ -1,48 +0,0 @@
-Extensions
-==========
-
-Extensions are extra packages that add functionality to a Flask
-application. For example, an extension might add support for sending
-email or connecting to a database. Some extensions add entire new
-frameworks to help build certain types of applications, like a REST API.
-
-
-Finding Extensions
-------------------
-
-Flask extensions are usually named "Flask-Foo" or "Foo-Flask". You can
-search PyPI for packages tagged with `Framework :: Flask `_.
-
-
-Using Extensions
-----------------
-
-Consult each extension's documentation for installation, configuration,
-and usage instructions. Generally, extensions pull their own
-configuration from :attr:`app.config ` and are
-passed an application instance during initialization. For example,
-an extension called "Flask-Foo" might be used like this::
-
- from flask_foo import Foo
-
- foo = Foo()
-
- app = Flask(__name__)
- app.config.update(
- FOO_BAR='baz',
- FOO_SPAM='eggs',
- )
-
- foo.init_app(app)
-
-
-Building Extensions
--------------------
-
-While `PyPI `_ contains many Flask extensions, you may not find
-an extension that fits your need. If this is the case, you can create
-your own, and publish it for others to use as well. Read
-:doc:`extensiondev` to develop your own Flask extension.
-
-
-.. _pypi: https://pypi.org/search/?c=Framework+%3A%3A+Flask
diff --git a/docs/installation.rst b/docs/installation.rst
deleted file mode 100644
index 90a314bf..00000000
--- a/docs/installation.rst
+++ /dev/null
@@ -1,144 +0,0 @@
-Installation
-============
-
-
-Python Version
---------------
-
-We recommend using the latest version of Python. Flask supports Python 3.9 and newer.
-
-
-Dependencies
-------------
-
-These distributions will be installed automatically when installing Flask.
-
-* `Werkzeug`_ implements WSGI, the standard Python interface between
- applications and servers.
-* `Jinja`_ is a template language that renders the pages your application
- serves.
-* `MarkupSafe`_ comes with Jinja. It escapes untrusted input when rendering
- templates to avoid injection attacks.
-* `ItsDangerous`_ securely signs data to ensure its integrity. This is used
- to protect Flask's session cookie.
-* `Click`_ is a framework for writing command line applications. It provides
- the ``flask`` command and allows adding custom management commands.
-* `Blinker`_ provides support for :doc:`signals`.
-
-.. _Werkzeug: https://palletsprojects.com/p/werkzeug/
-.. _Jinja: https://palletsprojects.com/p/jinja/
-.. _MarkupSafe: https://palletsprojects.com/p/markupsafe/
-.. _ItsDangerous: https://palletsprojects.com/p/itsdangerous/
-.. _Click: https://palletsprojects.com/p/click/
-.. _Blinker: https://blinker.readthedocs.io/
-
-
-Optional dependencies
-~~~~~~~~~~~~~~~~~~~~~
-
-These distributions will not be installed automatically. Flask will detect and
-use them if you install them.
-
-* `python-dotenv`_ enables support for :ref:`dotenv` when running ``flask``
- commands.
-* `Watchdog`_ provides a faster, more efficient reloader for the development
- server.
-
-.. _python-dotenv: https://github.com/theskumar/python-dotenv#readme
-.. _watchdog: https://pythonhosted.org/watchdog/
-
-
-greenlet
-~~~~~~~~
-
-You may choose to use gevent or eventlet with your application. In this
-case, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is
-required.
-
-These are not minimum supported versions, they only indicate the first
-versions that added necessary features. You should use the latest
-versions of each.
-
-
-Virtual environments
---------------------
-
-Use a virtual environment to manage the dependencies for your project, both in
-development and in production.
-
-What problem does a virtual environment solve? The more Python projects you
-have, the more likely it is that you need to work with different versions of
-Python libraries, or even Python itself. Newer versions of libraries for one
-project can break compatibility in another project.
-
-Virtual environments are independent groups of Python libraries, one for each
-project. Packages installed for one project will not affect other projects or
-the operating system's packages.
-
-Python comes bundled with the :mod:`venv` module to create virtual
-environments.
-
-
-.. _install-create-env:
-
-Create an environment
-~~~~~~~~~~~~~~~~~~~~~
-
-Create a project folder and a :file:`.venv` folder within:
-
-.. tabs::
-
- .. group-tab:: macOS/Linux
-
- .. code-block:: text
-
- $ mkdir myproject
- $ cd myproject
- $ python3 -m venv .venv
-
- .. group-tab:: Windows
-
- .. code-block:: text
-
- > mkdir myproject
- > cd myproject
- > py -3 -m venv .venv
-
-
-.. _install-activate-env:
-
-Activate the environment
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Before you work on your project, activate the corresponding environment:
-
-.. tabs::
-
- .. group-tab:: macOS/Linux
-
- .. code-block:: text
-
- $ . .venv/bin/activate
-
- .. group-tab:: Windows
-
- .. code-block:: text
-
- > .venv\Scripts\activate
-
-Your shell prompt will change to show the name of the activated
-environment.
-
-
-Install Flask
--------------
-
-Within the activated environment, use the following command to install
-Flask:
-
-.. code-block:: sh
-
- $ pip install Flask
-
-Flask is now installed. Check out the :doc:`/quickstart` or go to the
-:doc:`Documentation Overview `.
diff --git a/docs/license.rst b/docs/license.rst
deleted file mode 100644
index 2a445f9c..00000000
--- a/docs/license.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-BSD-3-Clause License
-====================
-
-.. literalinclude:: ../LICENSE.txt
- :language: text
diff --git a/docs/lifecycle.rst b/docs/lifecycle.rst
deleted file mode 100644
index 2344d98a..00000000
--- a/docs/lifecycle.rst
+++ /dev/null
@@ -1,168 +0,0 @@
-Application Structure and Lifecycle
-===================================
-
-Flask makes it pretty easy to write a web application. But there are quite a few
-different parts to an application and to each request it handles. Knowing what happens
-during application setup, serving, and handling requests will help you know what's
-possible in Flask and how to structure your application.
-
-
-Application Setup
------------------
-
-The first step in creating a Flask application is creating the application object. Each
-Flask application is an instance of the :class:`.Flask` class, which collects all
-configuration, extensions, and views.
-
-.. code-block:: python
-
- from flask import Flask
-
- app = Flask(__name__)
- app.config.from_mapping(
- SECRET_KEY="dev",
- )
- app.config.from_prefixed_env()
-
- @app.route("/")
- def index():
- return "Hello, World!"
-
-This is known as the "application setup phase", it's the code you write that's outside
-any view functions or other handlers. It can be split up between different modules and
-sub-packages, but all code that you want to be part of your application must be imported
-in order for it to be registered.
-
-All application setup must be completed before you start serving your application and
-handling requests. This is because WSGI servers divide work between multiple workers, or
-can be distributed across multiple machines. If the configuration changed in one worker,
-there's no way for Flask to ensure consistency between other workers.
-
-Flask tries to help developers catch some of these setup ordering issues by showing an
-error if setup-related methods are called after requests are handled. In that case
-you'll see this error:
-
- The setup method 'route' can no longer be called on the application. It has already
- handled its first request, any changes will not be applied consistently.
- Make sure all imports, decorators, functions, etc. needed to set up the application
- are done before running it.
-
-However, it is not possible for Flask to detect all cases of out-of-order setup. In
-general, don't do anything to modify the ``Flask`` app object and ``Blueprint`` objects
-from within view functions that run during requests. This includes:
-
-- Adding routes, view functions, and other request handlers with ``@app.route``,
- ``@app.errorhandler``, ``@app.before_request``, etc.
-- Registering blueprints.
-- Loading configuration with ``app.config``.
-- Setting up the Jinja template environment with ``app.jinja_env``.
-- Setting a session interface, instead of the default itsdangerous cookie.
-- Setting a JSON provider with ``app.json``, instead of the default provider.
-- Creating and initializing Flask extensions.
-
-
-Serving the Application
------------------------
-
-Flask is a WSGI application framework. The other half of WSGI is the WSGI server. During
-development, Flask, through Werkzeug, provides a development WSGI server with the
-``flask run`` CLI command. When you are done with development, use a production server
-to serve your application, see :doc:`deploying/index`.
-
-Regardless of what server you're using, it will follow the :pep:`3333` WSGI spec. The
-WSGI server will be told how to access your Flask application object, which is the WSGI
-application. Then it will start listening for HTTP requests, translate the request data
-into a WSGI environ, and call the WSGI application with that data. The WSGI application
-will return data that is translated into an HTTP response.
-
-#. Browser or other client makes HTTP request.
-#. WSGI server receives request.
-#. WSGI server converts HTTP data to WSGI ``environ`` dict.
-#. WSGI server calls WSGI application with the ``environ``.
-#. Flask, the WSGI application, does all its internal processing to route the request
- to a view function, handle errors, etc.
-#. Flask translates View function return into WSGI response data, passes it to WSGI
- server.
-#. WSGI server creates and send an HTTP response.
-#. Client receives the HTTP response.
-
-
-Middleware
-~~~~~~~~~~
-
-The WSGI application above is a callable that behaves in a certain way. Middleware
-is a WSGI application that wraps another WSGI application. It's a similar concept to
-Python decorators. The outermost middleware will be called by the server. It can modify
-the data passed to it, then call the WSGI application (or further middleware) that it
-wraps, and so on. And it can take the return value of that call and modify it further.
-
-From the WSGI server's perspective, there is one WSGI application, the one it calls
-directly. Typically, Flask is the "real" application at the end of the chain of
-middleware. But even Flask can call further WSGI applications, although that's an
-advanced, uncommon use case.
-
-A common middleware you'll see used with Flask is Werkzeug's
-:class:`~werkzeug.middleware.proxy_fix.ProxyFix`, which modifies the request to look
-like it came directly from a client even if it passed through HTTP proxies on the way.
-There are other middleware that can handle serving static files, authentication, etc.
-
-
-How a Request is Handled
-------------------------
-
-For us, the interesting part of the steps above is when Flask gets called by the WSGI
-server (or middleware). At that point, it will do quite a lot to handle the request and
-generate the response. At the most basic, it will match the URL to a view function, call
-the view function, and pass the return value back to the server. But there are many more
-parts that you can use to customize its behavior.
-
-#. WSGI server calls the Flask object, which calls :meth:`.Flask.wsgi_app`.
-#. A :class:`.RequestContext` object is created. This converts the WSGI ``environ``
- dict into a :class:`.Request` object. It also creates an :class:`AppContext` object.
-#. The :doc:`app context ` is pushed, which makes :data:`.current_app` and
- :data:`.g` available.
-#. The :data:`.appcontext_pushed` signal is sent.
-#. The :doc:`request context ` is pushed, which makes :attr:`.request` and
- :class:`.session` available.
-#. The session is opened, loading any existing session data using the app's
- :attr:`~.Flask.session_interface`, an instance of :class:`.SessionInterface`.
-#. The URL is matched against the URL rules registered with the :meth:`~.Flask.route`
- decorator during application setup. If there is no match, the error - usually a 404,
- 405, or redirect - is stored to be handled later.
-#. The :data:`.request_started` signal is sent.
-#. Any :meth:`~.Flask.url_value_preprocessor` decorated functions are called.
-#. Any :meth:`~.Flask.before_request` decorated functions are called. If any of
- these function returns a value it is treated as the response immediately.
-#. If the URL didn't match a route a few steps ago, that error is raised now.
-#. The :meth:`~.Flask.route` decorated view function associated with the matched URL
- is called and returns a value to be used as the response.
-#. If any step so far raised an exception, and there is an :meth:`~.Flask.errorhandler`
- decorated function that matches the exception class or HTTP error code, it is
- called to handle the error and return a response.
-#. Whatever returned a response value - a before request function, the view, or an
- error handler, that value is converted to a :class:`.Response` object.
-#. Any :func:`~.after_this_request` decorated functions are called, then cleared.
-#. Any :meth:`~.Flask.after_request` decorated functions are called, which can modify
- the response object.
-#. The session is saved, persisting any modified session data using the app's
- :attr:`~.Flask.session_interface`.
-#. The :data:`.request_finished` signal is sent.
-#. If any step so far raised an exception, and it was not handled by an error handler
- function, it is handled now. HTTP exceptions are treated as responses with their
- corresponding status code, other exceptions are converted to a generic 500 response.
- The :data:`.got_request_exception` signal is sent.
-#. The response object's status, headers, and body are returned to the WSGI server.
-#. Any :meth:`~.Flask.teardown_request` decorated functions are called.
-#. The :data:`.request_tearing_down` signal is sent.
-#. The request context is popped, :attr:`.request` and :class:`.session` are no longer
- available.
-#. Any :meth:`~.Flask.teardown_appcontext` decorated functions are called.
-#. The :data:`.appcontext_tearing_down` signal is sent.
-#. The app context is popped, :data:`.current_app` and :data:`.g` are no longer
- available.
-#. The :data:`.appcontext_popped` signal is sent.
-
-There are even more decorators and customization points than this, but that aren't part
-of every request lifecycle. They're more specific to certain things you might use during
-a request, such as templates, building URLs, or handling JSON data. See the rest of this
-documentation, as well as the :doc:`api` to explore further.
diff --git a/docs/logging.rst b/docs/logging.rst
deleted file mode 100644
index 39588242..00000000
--- a/docs/logging.rst
+++ /dev/null
@@ -1,183 +0,0 @@
-Logging
-=======
-
-Flask uses standard Python :mod:`logging`. Messages about your Flask
-application are logged with :meth:`app.logger `,
-which takes the same name as :attr:`app.name `. This
-logger can also be used to log your own messages.
-
-.. code-block:: python
-
- @app.route('/login', methods=['POST'])
- def login():
- user = get_user(request.form['username'])
-
- if user.check_password(request.form['password']):
- login_user(user)
- app.logger.info('%s logged in successfully', user.username)
- return redirect(url_for('index'))
- else:
- app.logger.info('%s failed to log in', user.username)
- abort(401)
-
-If you don't configure logging, Python's default log level is usually
-'warning'. Nothing below the configured level will be visible.
-
-
-Basic Configuration
--------------------
-
-When you want to configure logging for your project, you should do it as soon
-as possible when the program starts. If :meth:`app.logger `
-is accessed before logging is configured, it will add a default handler. If
-possible, configure logging before creating the application object.
-
-This example uses :func:`~logging.config.dictConfig` to create a logging
-configuration similar to Flask's default, except for all logs::
-
- from logging.config import dictConfig
-
- dictConfig({
- 'version': 1,
- 'formatters': {'default': {
- 'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
- }},
- 'handlers': {'wsgi': {
- 'class': 'logging.StreamHandler',
- 'stream': 'ext://flask.logging.wsgi_errors_stream',
- 'formatter': 'default'
- }},
- 'root': {
- 'level': 'INFO',
- 'handlers': ['wsgi']
- }
- })
-
- app = Flask(__name__)
-
-
-Default Configuration
-`````````````````````
-
-If you do not configure logging yourself, Flask will add a
-:class:`~logging.StreamHandler` to :meth:`app.logger `
-automatically. During requests, it will write to the stream specified by the
-WSGI server in ``environ['wsgi.errors']`` (which is usually
-:data:`sys.stderr`). Outside a request, it will log to :data:`sys.stderr`.
-
-
-Removing the Default Handler
-````````````````````````````
-
-If you configured logging after accessing
-:meth:`app.logger `, and need to remove the default
-handler, you can import and remove it::
-
- from flask.logging import default_handler
-
- app.logger.removeHandler(default_handler)
-
-
-Email Errors to Admins
-----------------------
-
-When running the application on a remote server for production, you probably
-won't be looking at the log messages very often. The WSGI server will probably
-send log messages to a file, and you'll only check that file if a user tells
-you something went wrong.
-
-To be proactive about discovering and fixing bugs, you can configure a
-:class:`logging.handlers.SMTPHandler` to send an email when errors and higher
-are logged. ::
-
- import logging
- from logging.handlers import SMTPHandler
-
- mail_handler = SMTPHandler(
- mailhost='127.0.0.1',
- fromaddr='server-error@example.com',
- toaddrs=['admin@example.com'],
- subject='Application Error'
- )
- mail_handler.setLevel(logging.ERROR)
- mail_handler.setFormatter(logging.Formatter(
- '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
- ))
-
- if not app.debug:
- app.logger.addHandler(mail_handler)
-
-This requires that you have an SMTP server set up on the same server. See the
-Python docs for more information about configuring the handler.
-
-
-Injecting Request Information
------------------------------
-
-Seeing more information about the request, such as the IP address, may help
-debugging some errors. You can subclass :class:`logging.Formatter` to inject
-your own fields that can be used in messages. You can change the formatter for
-Flask's default handler, the mail handler defined above, or any other
-handler. ::
-
- from flask import has_request_context, request
- from flask.logging import default_handler
-
- class RequestFormatter(logging.Formatter):
- def format(self, record):
- if has_request_context():
- record.url = request.url
- record.remote_addr = request.remote_addr
- else:
- record.url = None
- record.remote_addr = None
-
- return super().format(record)
-
- formatter = RequestFormatter(
- '[%(asctime)s] %(remote_addr)s requested %(url)s\n'
- '%(levelname)s in %(module)s: %(message)s'
- )
- default_handler.setFormatter(formatter)
- mail_handler.setFormatter(formatter)
-
-
-Other Libraries
----------------
-
-Other libraries may use logging extensively, and you want to see relevant
-messages from those logs too. The simplest way to do this is to add handlers
-to the root logger instead of only the app logger. ::
-
- from flask.logging import default_handler
-
- root = logging.getLogger()
- root.addHandler(default_handler)
- root.addHandler(mail_handler)
-
-Depending on your project, it may be more useful to configure each logger you
-care about separately, instead of configuring only the root logger. ::
-
- for logger in (
- logging.getLogger(app.name),
- logging.getLogger('sqlalchemy'),
- logging.getLogger('other_package'),
- ):
- logger.addHandler(default_handler)
- logger.addHandler(mail_handler)
-
-
-Werkzeug
-````````
-
-Werkzeug logs basic request/response information to the ``'werkzeug'`` logger.
-If the root logger has no handlers configured, Werkzeug adds a
-:class:`~logging.StreamHandler` to its logger.
-
-
-Flask Extensions
-````````````````
-
-Depending on the situation, an extension may choose to log to
-:meth:`app.logger ` or its own named logger. Consult each
-extension's documentation for details.
diff --git a/docs/make.bat b/docs/make.bat
index 922152e9..747ffb7b 100644
--- a/docs/make.bat
+++ b/docs/make.bat
@@ -1,35 +1,35 @@
-@ECHO OFF
-
-pushd %~dp0
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
- set SPHINXBUILD=sphinx-build
-)
-set SOURCEDIR=.
-set BUILDDIR=_build
-
-if "%1" == "" goto help
-
-%SPHINXBUILD% >NUL 2>NUL
-if errorlevel 9009 (
- echo.
- echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
- echo.installed, then set the SPHINXBUILD environment variable to point
- echo.to the full path of the 'sphinx-build' executable. Alternatively you
- echo.may add the Sphinx directory to PATH.
- echo.
- echo.If you don't have Sphinx installed, grab it from
- echo.http://sphinx-doc.org/
- exit /b 1
-)
-
-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
-goto end
-
-:help
-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
-
-:end
-popd
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/docs/patterns/appdispatch.rst b/docs/patterns/appdispatch.rst
deleted file mode 100644
index f22c8060..00000000
--- a/docs/patterns/appdispatch.rst
+++ /dev/null
@@ -1,189 +0,0 @@
-Application Dispatching
-=======================
-
-Application dispatching is the process of combining multiple Flask
-applications on the WSGI level. You can combine not only Flask
-applications but any WSGI application. This would allow you to run a
-Django and a Flask application in the same interpreter side by side if
-you want. The usefulness of this depends on how the applications work
-internally.
-
-The fundamental difference from :doc:`packages` is that in this case you
-are running the same or different Flask applications that are entirely
-isolated from each other. They run different configurations and are
-dispatched on the WSGI level.
-
-
-Working with this Document
---------------------------
-
-Each of the techniques and examples below results in an ``application``
-object that can be run with any WSGI server. For development, use the
-``flask run`` command to start a development server. For production, see
-:doc:`/deploying/index`.
-
-.. code-block:: python
-
- from flask import Flask
-
- app = Flask(__name__)
-
- @app.route('/')
- def hello_world():
- return 'Hello World!'
-
-
-Combining Applications
-----------------------
-
-If you have entirely separated applications and you want them to work next
-to each other in the same Python interpreter process you can take
-advantage of the :class:`werkzeug.wsgi.DispatcherMiddleware`. The idea
-here is that each Flask application is a valid WSGI application and they
-are combined by the dispatcher middleware into a larger one that is
-dispatched based on prefix.
-
-For example you could have your main application run on ``/`` and your
-backend interface on ``/backend``.
-
-.. code-block:: python
-
- from werkzeug.middleware.dispatcher import DispatcherMiddleware
- from frontend_app import application as frontend
- from backend_app import application as backend
-
- application = DispatcherMiddleware(frontend, {
- '/backend': backend
- })
-
-
-Dispatch by Subdomain
----------------------
-
-Sometimes you might want to use multiple instances of the same application
-with different configurations. Assuming the application is created inside
-a function and you can call that function to instantiate it, that is
-really easy to implement. In order to develop your application to support
-creating new instances in functions have a look at the
-:doc:`appfactories` pattern.
-
-A very common example would be creating applications per subdomain. For
-instance you configure your webserver to dispatch all requests for all
-subdomains to your application and you then use the subdomain information
-to create user-specific instances. Once you have your server set up to
-listen on all subdomains you can use a very simple WSGI application to do
-the dynamic application creation.
-
-The perfect level for abstraction in that regard is the WSGI layer. You
-write your own WSGI application that looks at the request that comes and
-delegates it to your Flask application. If that application does not
-exist yet, it is dynamically created and remembered.
-
-.. code-block:: python
-
- from threading import Lock
-
- class SubdomainDispatcher:
-
- def __init__(self, domain, create_app):
- self.domain = domain
- self.create_app = create_app
- self.lock = Lock()
- self.instances = {}
-
- def get_application(self, host):
- host = host.split(':')[0]
- assert host.endswith(self.domain), 'Configuration error'
- subdomain = host[:-len(self.domain)].rstrip('.')
- with self.lock:
- app = self.instances.get(subdomain)
- if app is None:
- app = self.create_app(subdomain)
- self.instances[subdomain] = app
- return app
-
- def __call__(self, environ, start_response):
- app = self.get_application(environ['HTTP_HOST'])
- return app(environ, start_response)
-
-
-This dispatcher can then be used like this:
-
-.. code-block:: python
-
- from myapplication import create_app, get_user_for_subdomain
- from werkzeug.exceptions import NotFound
-
- def make_app(subdomain):
- user = get_user_for_subdomain(subdomain)
- if user is None:
- # if there is no user for that subdomain we still have
- # to return a WSGI application that handles that request.
- # We can then just return the NotFound() exception as
- # application which will render a default 404 page.
- # You might also redirect the user to the main page then
- return NotFound()
-
- # otherwise create the application for the specific user
- return create_app(user)
-
- application = SubdomainDispatcher('example.com', make_app)
-
-
-Dispatch by Path
-----------------
-
-Dispatching by a path on the URL is very similar. Instead of looking at
-the ``Host`` header to figure out the subdomain one simply looks at the
-request path up to the first slash.
-
-.. code-block:: python
-
- from threading import Lock
- from wsgiref.util import shift_path_info
-
- class PathDispatcher:
-
- def __init__(self, default_app, create_app):
- self.default_app = default_app
- self.create_app = create_app
- self.lock = Lock()
- self.instances = {}
-
- def get_application(self, prefix):
- with self.lock:
- app = self.instances.get(prefix)
- if app is None:
- app = self.create_app(prefix)
- if app is not None:
- self.instances[prefix] = app
- return app
-
- def __call__(self, environ, start_response):
- app = self.get_application(_peek_path_info(environ))
- if app is not None:
- shift_path_info(environ)
- else:
- app = self.default_app
- return app(environ, start_response)
-
- def _peek_path_info(environ):
- segments = environ.get("PATH_INFO", "").lstrip("/").split("/", 1)
- if segments:
- return segments[0]
-
- return None
-
-The big difference between this and the subdomain one is that this one
-falls back to another application if the creator function returns ``None``.
-
-.. code-block:: python
-
- from myapplication import create_app, default_app, get_user_for_prefix
-
- def make_app(prefix):
- user = get_user_for_prefix(prefix)
- if user is not None:
- return create_app(user)
-
- application = PathDispatcher(default_app, make_app)
diff --git a/docs/patterns/appfactories.rst b/docs/patterns/appfactories.rst
deleted file mode 100644
index 0f248783..00000000
--- a/docs/patterns/appfactories.rst
+++ /dev/null
@@ -1,118 +0,0 @@
-Application Factories
-=====================
-
-If you are already using packages and blueprints for your application
-(:doc:`/blueprints`) there are a couple of really nice ways to further improve
-the experience. A common pattern is creating the application object when
-the blueprint is imported. But if you move the creation of this object
-into a function, you can then create multiple instances of this app later.
-
-So why would you want to do this?
-
-1. Testing. You can have instances of the application with different
- settings to test every case.
-2. Multiple instances. Imagine you want to run different versions of the
- same application. Of course you could have multiple instances with
- different configs set up in your webserver, but if you use factories,
- you can have multiple instances of the same application running in the
- same application process which can be handy.
-
-So how would you then actually implement that?
-
-Basic Factories
----------------
-
-The idea is to set up the application in a function. Like this::
-
- def create_app(config_filename):
- app = Flask(__name__)
- app.config.from_pyfile(config_filename)
-
- from yourapplication.model import db
- db.init_app(app)
-
- from yourapplication.views.admin import admin
- from yourapplication.views.frontend import frontend
- app.register_blueprint(admin)
- app.register_blueprint(frontend)
-
- return app
-
-The downside is that you cannot use the application object in the blueprints
-at import time. You can however use it from within a request. How do you
-get access to the application with the config? Use
-:data:`~flask.current_app`::
-
- from flask import current_app, Blueprint, render_template
- admin = Blueprint('admin', __name__, url_prefix='/admin')
-
- @admin.route('/')
- def index():
- return render_template(current_app.config['INDEX_TEMPLATE'])
-
-Here we look up the name of a template in the config.
-
-Factories & Extensions
-----------------------
-
-It's preferable to create your extensions and app factories so that the
-extension object does not initially get bound to the application.
-
-Using `Flask-SQLAlchemy `_,
-as an example, you should not do something along those lines::
-
- def create_app(config_filename):
- app = Flask(__name__)
- app.config.from_pyfile(config_filename)
-
- db = SQLAlchemy(app)
-
-But, rather, in model.py (or equivalent)::
-
- db = SQLAlchemy()
-
-and in your application.py (or equivalent)::
-
- def create_app(config_filename):
- app = Flask(__name__)
- app.config.from_pyfile(config_filename)
-
- from yourapplication.model import db
- db.init_app(app)
-
-Using this design pattern, no application-specific state is stored on the
-extension object, so one extension object can be used for multiple apps.
-For more information about the design of extensions refer to :doc:`/extensiondev`.
-
-Using Applications
-------------------
-
-To run such an application, you can use the :command:`flask` command:
-
-.. code-block:: text
-
- $ flask --app hello run
-
-Flask will automatically detect the factory if it is named
-``create_app`` or ``make_app`` in ``hello``. You can also pass arguments
-to the factory like this:
-
-.. code-block:: text
-
- $ flask --app 'hello:create_app(local_auth=True)' run
-
-Then the ``create_app`` factory in ``hello`` is called with the keyword
-argument ``local_auth=True``. See :doc:`/cli` for more detail.
-
-Factory Improvements
---------------------
-
-The factory function above is not very clever, but you can improve it.
-The following changes are straightforward to implement:
-
-1. Make it possible to pass in configuration values for unit tests so that
- you don't have to create config files on the filesystem.
-2. Call a function from a blueprint when the application is setting up so
- that you have a place to modify attributes of the application (like
- hooking in before/after request handlers etc.)
-3. Add in WSGI middlewares when the application is being created if necessary.
diff --git a/docs/patterns/caching.rst b/docs/patterns/caching.rst
deleted file mode 100644
index 9bf7b72a..00000000
--- a/docs/patterns/caching.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-Caching
-=======
-
-When your application runs slow, throw some caches in. Well, at least
-it's the easiest way to speed up things. What does a cache do? Say you
-have a function that takes some time to complete but the results would
-still be good enough if they were 5 minutes old. So then the idea is that
-you actually put the result of that calculation into a cache for some
-time.
-
-Flask itself does not provide caching for you, but `Flask-Caching`_, an
-extension for Flask does. Flask-Caching supports various backends, and it is
-even possible to develop your own caching backend.
-
-
-.. _Flask-Caching: https://flask-caching.readthedocs.io/en/latest/
diff --git a/docs/patterns/celery.rst b/docs/patterns/celery.rst
deleted file mode 100644
index 2e9a43a7..00000000
--- a/docs/patterns/celery.rst
+++ /dev/null
@@ -1,242 +0,0 @@
-Background Tasks with Celery
-============================
-
-If your application has a long running task, such as processing some uploaded data or
-sending email, you don't want to wait for it to finish during a request. Instead, use a
-task queue to send the necessary data to another process that will run the task in the
-background while the request returns immediately.
-
-`Celery`_ is a powerful task queue that can be used for simple background tasks as well
-as complex multi-stage programs and schedules. This guide will show you how to configure
-Celery using Flask. Read Celery's `First Steps with Celery`_ guide to learn how to use
-Celery itself.
-
-.. _Celery: https://celery.readthedocs.io
-.. _First Steps with Celery: https://celery.readthedocs.io/en/latest/getting-started/first-steps-with-celery.html
-
-The Flask repository contains `an example `_
-based on the information on this page, which also shows how to use JavaScript to submit
-tasks and poll for progress and results.
-
-
-Install
--------
-
-Install Celery from PyPI, for example using pip:
-
-.. code-block:: text
-
- $ pip install celery
-
-
-Integrate Celery with Flask
----------------------------
-
-You can use Celery without any integration with Flask, but it's convenient to configure
-it through Flask's config, and to let tasks access the Flask application.
-
-Celery uses similar ideas to Flask, with a ``Celery`` app object that has configuration
-and registers tasks. While creating a Flask app, use the following code to create and
-configure a Celery app as well.
-
-.. code-block:: python
-
- from celery import Celery, Task
-
- def celery_init_app(app: Flask) -> Celery:
- class FlaskTask(Task):
- def __call__(self, *args: object, **kwargs: object) -> object:
- with app.app_context():
- return self.run(*args, **kwargs)
-
- celery_app = Celery(app.name, task_cls=FlaskTask)
- celery_app.config_from_object(app.config["CELERY"])
- celery_app.set_default()
- app.extensions["celery"] = celery_app
- return celery_app
-
-This creates and returns a ``Celery`` app object. Celery `configuration`_ is taken from
-the ``CELERY`` key in the Flask configuration. The Celery app is set as the default, so
-that it is seen during each request. The ``Task`` subclass automatically runs task
-functions with a Flask app context active, so that services like your database
-connections are available.
-
-.. _configuration: https://celery.readthedocs.io/en/stable/userguide/configuration.html
-
-Here's a basic ``example.py`` that configures Celery to use Redis for communication. We
-enable a result backend, but ignore results by default. This allows us to store results
-only for tasks where we care about the result.
-
-.. code-block:: python
-
- from flask import Flask
-
- app = Flask(__name__)
- app.config.from_mapping(
- CELERY=dict(
- broker_url="redis://localhost",
- result_backend="redis://localhost",
- task_ignore_result=True,
- ),
- )
- celery_app = celery_init_app(app)
-
-Point the ``celery worker`` command at this and it will find the ``celery_app`` object.
-
-.. code-block:: text
-
- $ celery -A example worker --loglevel INFO
-
-You can also run the ``celery beat`` command to run tasks on a schedule. See Celery's
-docs for more information about defining schedules.
-
-.. code-block:: text
-
- $ celery -A example beat --loglevel INFO
-
-
-Application Factory
--------------------
-
-When using the Flask application factory pattern, call the ``celery_init_app`` function
-inside the factory. It sets ``app.extensions["celery"]`` to the Celery app object, which
-can be used to get the Celery app from the Flask app returned by the factory.
-
-.. code-block:: python
-
- def create_app() -> Flask:
- app = Flask(__name__)
- app.config.from_mapping(
- CELERY=dict(
- broker_url="redis://localhost",
- result_backend="redis://localhost",
- task_ignore_result=True,
- ),
- )
- app.config.from_prefixed_env()
- celery_init_app(app)
- return app
-
-To use ``celery`` commands, Celery needs an app object, but that's no longer directly
-available. Create a ``make_celery.py`` file that calls the Flask app factory and gets
-the Celery app from the returned Flask app.
-
-.. code-block:: python
-
- from example import create_app
-
- flask_app = create_app()
- celery_app = flask_app.extensions["celery"]
-
-Point the ``celery`` command to this file.
-
-.. code-block:: text
-
- $ celery -A make_celery worker --loglevel INFO
- $ celery -A make_celery beat --loglevel INFO
-
-
-Defining Tasks
---------------
-
-Using ``@celery_app.task`` to decorate task functions requires access to the
-``celery_app`` object, which won't be available when using the factory pattern. It also
-means that the decorated tasks are tied to the specific Flask and Celery app instances,
-which could be an issue during testing if you change configuration for a test.
-
-Instead, use Celery's ``@shared_task`` decorator. This creates task objects that will
-access whatever the "current app" is, which is a similar concept to Flask's blueprints
-and app context. This is why we called ``celery_app.set_default()`` above.
-
-Here's an example task that adds two numbers together and returns the result.
-
-.. code-block:: python
-
- from celery import shared_task
-
- @shared_task(ignore_result=False)
- def add_together(a: int, b: int) -> int:
- return a + b
-
-Earlier, we configured Celery to ignore task results by default. Since we want to know
-the return value of this task, we set ``ignore_result=False``. On the other hand, a task
-that didn't need a result, such as sending an email, wouldn't set this.
-
-
-Calling Tasks
--------------
-
-The decorated function becomes a task object with methods to call it in the background.
-The simplest way is to use the ``delay(*args, **kwargs)`` method. See Celery's docs for
-more methods.
-
-A Celery worker must be running to run the task. Starting a worker is shown in the
-previous sections.
-
-.. code-block:: python
-
- from flask import request
-
- @app.post("/add")
- def start_add() -> dict[str, object]:
- a = request.form.get("a", type=int)
- b = request.form.get("b", type=int)
- result = add_together.delay(a, b)
- return {"result_id": result.id}
-
-The route doesn't get the task's result immediately. That would defeat the purpose by
-blocking the response. Instead, we return the running task's result id, which we can use
-later to get the result.
-
-
-Getting Results
----------------
-
-To fetch the result of the task we started above, we'll add another route that takes the
-result id we returned before. We return whether the task is finished (ready), whether it
-finished successfully, and what the return value (or error) was if it is finished.
-
-.. code-block:: python
-
- from celery.result import AsyncResult
-
- @app.get("/result/")
- def task_result(id: str) -> dict[str, object]:
- result = AsyncResult(id)
- return {
- "ready": result.ready(),
- "successful": result.successful(),
- "value": result.result if result.ready() else None,
- }
-
-Now you can start the task using the first route, then poll for the result using the
-second route. This keeps the Flask request workers from being blocked waiting for tasks
-to finish.
-
-The Flask repository contains `an example `_
-using JavaScript to submit tasks and poll for progress and results.
-
-
-Passing Data to Tasks
----------------------
-
-The "add" task above took two integers as arguments. To pass arguments to tasks, Celery
-has to serialize them to a format that it can pass to other processes. Therefore,
-passing complex objects is not recommended. For example, it would be impossible to pass
-a SQLAlchemy model object, since that object is probably not serializable and is tied to
-the session that queried it.
-
-Pass the minimal amount of data necessary to fetch or recreate any complex data within
-the task. Consider a task that will run when the logged in user asks for an archive of
-their data. The Flask request knows the logged in user, and has the user object queried
-from the database. It got that by querying the database for a given id, so the task can
-do the same thing. Pass the user's id rather than the user object.
-
-.. code-block:: python
-
- @shared_task
- def generate_user_archive(user_id: str) -> None:
- user = db.session.get(User, user_id)
- ...
-
- generate_user_archive.delay(current_user.id)
diff --git a/docs/patterns/deferredcallbacks.rst b/docs/patterns/deferredcallbacks.rst
deleted file mode 100644
index 4ff8814b..00000000
--- a/docs/patterns/deferredcallbacks.rst
+++ /dev/null
@@ -1,44 +0,0 @@
-Deferred Request Callbacks
-==========================
-
-One of the design principles of Flask is that response objects are created and
-passed down a chain of potential callbacks that can modify them or replace
-them. When the request handling starts, there is no response object yet. It is
-created as necessary either by a view function or by some other component in
-the system.
-
-What happens if you want to modify the response at a point where the response
-does not exist yet? A common example for that would be a
-:meth:`~flask.Flask.before_request` callback that wants to set a cookie on the
-response object.
-
-One way is to avoid the situation. Very often that is possible. For instance
-you can try to move that logic into a :meth:`~flask.Flask.after_request`
-callback instead. However, sometimes moving code there makes it
-more complicated or awkward to reason about.
-
-As an alternative, you can use :func:`~flask.after_this_request` to register
-callbacks that will execute after only the current request. This way you can
-defer code execution from anywhere in the application, based on the current
-request.
-
-At any time during a request, we can register a function to be called at the
-end of the request. For example you can remember the current language of the
-user in a cookie in a :meth:`~flask.Flask.before_request` callback::
-
- from flask import request, after_this_request
-
- @app.before_request
- def detect_user_language():
- language = request.cookies.get('user_lang')
-
- if language is None:
- language = guess_language_from_request()
-
- # when the response exists, set a cookie with the language
- @after_this_request
- def remember_language(response):
- response.set_cookie('user_lang', language)
- return response
-
- g.language = language
diff --git a/docs/patterns/favicon.rst b/docs/patterns/favicon.rst
deleted file mode 100644
index b867854f..00000000
--- a/docs/patterns/favicon.rst
+++ /dev/null
@@ -1,56 +0,0 @@
-Adding a favicon
-================
-
-A "favicon" is an icon used by browsers for tabs and bookmarks. This helps
-to distinguish your website and to give it a unique brand.
-
-A common question is how to add a favicon to a Flask application. First, of
-course, you need an icon. It should be 16 × 16 pixels and in the ICO file
-format. This is not a requirement but a de-facto standard supported by all
-relevant browsers. Put the icon in your static directory as
-:file:`favicon.ico`.
-
-Now, to get browsers to find your icon, the correct way is to add a link
-tag in your HTML. So, for example:
-
-.. sourcecode:: html+jinja
-
-
-
-That's all you need for most browsers, however some really old ones do not
-support this standard. The old de-facto standard is to serve this file,
-with this name, at the website root. If your application is not mounted at
-the root path of the domain you either need to configure the web server to
-serve the icon at the root or if you can't do that you're out of luck. If
-however your application is the root you can simply route a redirect::
-
- app.add_url_rule(
- "/favicon.ico",
- endpoint="favicon",
- redirect_to=url_for("static", filename="favicon.ico"),
- )
-
-If you want to save the extra redirect request you can also write a view
-using :func:`~flask.send_from_directory`::
-
- import os
- from flask import send_from_directory
-
- @app.route('/favicon.ico')
- def favicon():
- return send_from_directory(os.path.join(app.root_path, 'static'),
- 'favicon.ico', mimetype='image/vnd.microsoft.icon')
-
-We can leave out the explicit mimetype and it will be guessed, but we may
-as well specify it to avoid the extra guessing, as it will always be the
-same.
-
-The above will serve the icon via your application and if possible it's
-better to configure your dedicated web server to serve it; refer to the
-web server's documentation.
-
-See also
---------
-
-* The `Favicon `_ article on
- Wikipedia
diff --git a/docs/patterns/fileuploads.rst b/docs/patterns/fileuploads.rst
deleted file mode 100644
index 304f57dc..00000000
--- a/docs/patterns/fileuploads.rst
+++ /dev/null
@@ -1,182 +0,0 @@
-Uploading Files
-===============
-
-Ah yes, the good old problem of file uploads. The basic idea of file
-uploads is actually quite simple. It basically works like this:
-
-1. A ``
- '''
-
-So what does that :func:`~werkzeug.utils.secure_filename` function actually do?
-Now the problem is that there is that principle called "never trust user
-input". This is also true for the filename of an uploaded file. All
-submitted form data can be forged, and filenames can be dangerous. For
-the moment just remember: always use that function to secure a filename
-before storing it directly on the filesystem.
-
-.. admonition:: Information for the Pros
-
- So you're interested in what that :func:`~werkzeug.utils.secure_filename`
- function does and what the problem is if you're not using it? So just
- imagine someone would send the following information as `filename` to
- your application::
-
- filename = "../../../../home/username/.bashrc"
-
- Assuming the number of ``../`` is correct and you would join this with
- the ``UPLOAD_FOLDER`` the user might have the ability to modify a file on
- the server's filesystem he or she should not modify. This does require some
- knowledge about how the application looks like, but trust me, hackers
- are patient :)
-
- Now let's look how that function works:
-
- >>> secure_filename('../../../../home/username/.bashrc')
- 'home_username_.bashrc'
-
-We want to be able to serve the uploaded files so they can be downloaded
-by users. We'll define a ``download_file`` view to serve files in the
-upload folder by name. ``url_for("download_file", name=name)`` generates
-download URLs.
-
-.. code-block:: python
-
- from flask import send_from_directory
-
- @app.route('/uploads/')
- def download_file(name):
- return send_from_directory(app.config["UPLOAD_FOLDER"], name)
-
-If you're using middleware or the HTTP server to serve files, you can
-register the ``download_file`` endpoint as ``build_only`` so ``url_for``
-will work without a view function.
-
-.. code-block:: python
-
- app.add_url_rule(
- "/uploads/", endpoint="download_file", build_only=True
- )
-
-
-Improving Uploads
------------------
-
-.. versionadded:: 0.6
-
-So how exactly does Flask handle uploads? Well it will store them in the
-webserver's memory if the files are reasonably small, otherwise in a
-temporary location (as returned by :func:`tempfile.gettempdir`). But how
-do you specify the maximum file size after which an upload is aborted? By
-default Flask will happily accept file uploads with an unlimited amount of
-memory, but you can limit that by setting the ``MAX_CONTENT_LENGTH``
-config key::
-
- from flask import Flask, Request
-
- app = Flask(__name__)
- app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000
-
-The code above will limit the maximum allowed payload to 16 megabytes.
-If a larger file is transmitted, Flask will raise a
-:exc:`~werkzeug.exceptions.RequestEntityTooLarge` exception.
-
-.. admonition:: Connection Reset Issue
-
- When using the local development server, you may get a connection
- reset error instead of a 413 response. You will get the correct
- status response when running the app with a production WSGI server.
-
-This feature was added in Flask 0.6 but can be achieved in older versions
-as well by subclassing the request object. For more information on that
-consult the Werkzeug documentation on file handling.
-
-
-Upload Progress Bars
---------------------
-
-A while ago many developers had the idea to read the incoming file in
-small chunks and store the upload progress in the database to be able to
-poll the progress with JavaScript from the client. The client asks the
-server every 5 seconds how much it has transmitted, but this is
-something it should already know.
-
-An Easier Solution
-------------------
-
-Now there are better solutions that work faster and are more reliable. There
-are JavaScript libraries like jQuery_ that have form plugins to ease the
-construction of progress bar.
-
-Because the common pattern for file uploads exists almost unchanged in all
-applications dealing with uploads, there are also some Flask extensions that
-implement a full fledged upload mechanism that allows controlling which
-file extensions are allowed to be uploaded.
-
-.. _jQuery: https://jquery.com/
diff --git a/docs/patterns/flashing.rst b/docs/patterns/flashing.rst
deleted file mode 100644
index 8eb6b3ac..00000000
--- a/docs/patterns/flashing.rst
+++ /dev/null
@@ -1,148 +0,0 @@
-Message Flashing
-================
-
-Good applications and user interfaces are all about feedback. If the user
-does not get enough feedback they will probably end up hating the
-application. Flask provides a really simple way to give feedback to a
-user with the flashing system. The flashing system basically makes it
-possible to record a message at the end of a request and access it next
-request and only next request. This is usually combined with a layout
-template that does this. Note that browsers and sometimes web servers enforce
-a limit on cookie sizes. This means that flashing messages that are too
-large for session cookies causes message flashing to fail silently.
-
-Simple Flashing
----------------
-
-So here is a full example::
-
- from flask import Flask, flash, redirect, render_template, \
- request, url_for
-
- app = Flask(__name__)
- app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
-
- @app.route('/')
- def index():
- return render_template('index.html')
-
- @app.route('/login', methods=['GET', 'POST'])
- def login():
- error = None
- if request.method == 'POST':
- if request.form['username'] != 'admin' or \
- request.form['password'] != 'secret':
- error = 'Invalid credentials'
- else:
- flash('You were successfully logged in')
- return redirect(url_for('index'))
- return render_template('login.html', error=error)
-
-And here is the :file:`layout.html` template which does the magic:
-
-.. sourcecode:: html+jinja
-
-
- My Application
- {% with messages = get_flashed_messages() %}
- {% if messages %}
-
- {% for message in messages %}
-
{{ message }}
- {% endfor %}
-
- {% endif %}
- {% endwith %}
- {% block body %}{% endblock %}
-
-Here is the :file:`index.html` template which inherits from :file:`layout.html`:
-
-.. sourcecode:: html+jinja
-
- {% extends "layout.html" %}
- {% block body %}
-
Overview
-
Do you want to log in?
- {% endblock %}
-
-And here is the :file:`login.html` template which also inherits from
-:file:`layout.html`:
-
-.. sourcecode:: html+jinja
-
- {% extends "layout.html" %}
- {% block body %}
-
Login
- {% if error %}
-
Error: {{ error }}
- {% endif %}
-
- {% endblock %}
-
-Flashing With Categories
-------------------------
-
-.. versionadded:: 0.3
-
-It is also possible to provide categories when flashing a message. The
-default category if nothing is provided is ``'message'``. Alternative
-categories can be used to give the user better feedback. For example
-error messages could be displayed with a red background.
-
-To flash a message with a different category, just use the second argument
-to the :func:`~flask.flash` function::
-
- flash('Invalid password provided', 'error')
-
-Inside the template you then have to tell the
-:func:`~flask.get_flashed_messages` function to also return the
-categories. The loop looks slightly different in that situation then:
-
-.. sourcecode:: html+jinja
-
- {% with messages = get_flashed_messages(with_categories=true) %}
- {% if messages %}
-
- {% for category, message in messages %}
-
{{ message }}
- {% endfor %}
-
- {% endif %}
- {% endwith %}
-
-This is just one example of how to render these flashed messages. One
-might also use the category to add a prefix such as
-``Error:`` to the message.
-
-Filtering Flash Messages
-------------------------
-
-.. versionadded:: 0.9
-
-Optionally you can pass a list of categories which filters the results of
-:func:`~flask.get_flashed_messages`. This is useful if you wish to
-render each category in a separate block.
-
-.. sourcecode:: html+jinja
-
- {% with errors = get_flashed_messages(category_filter=["error"]) %}
- {% if errors %}
-
- {% endif %}
- {% endwith %}
diff --git a/docs/patterns/index.rst b/docs/patterns/index.rst
deleted file mode 100644
index 1f2c07dd..00000000
--- a/docs/patterns/index.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-Patterns for Flask
-==================
-
-Certain features and interactions are common enough that you will find
-them in most web applications. For example, many applications use a
-relational database and user authentication. They will open a database
-connection at the beginning of the request and get the information for
-the logged in user. At the end of the request, the database connection
-is closed.
-
-These types of patterns may be a bit outside the scope of Flask itself,
-but Flask makes it easy to implement them. Some common patterns are
-collected in the following pages.
-
-.. toctree::
- :maxdepth: 2
-
- packages
- appfactories
- appdispatch
- urlprocessors
- sqlite3
- sqlalchemy
- fileuploads
- caching
- viewdecorators
- wtforms
- templateinheritance
- flashing
- javascript
- lazyloading
- mongoengine
- favicon
- streaming
- deferredcallbacks
- methodoverrides
- requestchecksum
- celery
- subclassing
- singlepageapplications
diff --git a/docs/patterns/javascript.rst b/docs/patterns/javascript.rst
deleted file mode 100644
index d58a3eb6..00000000
--- a/docs/patterns/javascript.rst
+++ /dev/null
@@ -1,259 +0,0 @@
-JavaScript, ``fetch``, and JSON
-===============================
-
-You may want to make your HTML page dynamic, by changing data without
-reloading the entire page. Instead of submitting an HTML ``