update docs about contexts

This commit is contained in:
David Lord 2022-07-08 07:08:54 -07:00
parent 82c2e0366c
commit e0dad45481
No known key found for this signature in database
GPG key ID: 7A1C87E3F5BC42A8
9 changed files with 74 additions and 124 deletions

View file

@ -311,56 +311,28 @@ Useful Internals
.. autoclass:: flask.ctx.RequestContext
:members:
.. data:: _request_ctx_stack
.. data:: flask.globals.request_ctx
The internal :class:`~werkzeug.local.LocalStack` that holds
:class:`~flask.ctx.RequestContext` instances. Typically, the
:data:`request` and :data:`session` proxies should be accessed
instead of the stack. It may be useful to access the stack in
extension code.
The current :class:`~flask.ctx.RequestContext`. If a request context
is not active, accessing attributes on this proxy will raise a
``RuntimeError``.
The following attributes are always present on each layer of the
stack:
`app`
the active Flask application.
`url_adapter`
the URL adapter that was used to match the request.
`request`
the current request object.
`session`
the active session object.
`g`
an object with all the attributes of the :data:`flask.g` object.
`flashes`
an internal cache for the flashed messages.
Example usage::
from flask import _request_ctx_stack
def get_session():
ctx = _request_ctx_stack.top
if ctx is not None:
return ctx.session
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:: _app_ctx_stack
.. data:: flask.globals.app_ctx
The internal :class:`~werkzeug.local.LocalStack` that holds
:class:`~flask.ctx.AppContext` instances. Typically, the
:data:`current_app` and :data:`g` proxies should be accessed instead
of the stack. Extensions can access the contexts on the stack as a
namespace to store data.
The current :class:`~flask.ctx.AppContext`. If an app context is not
active, accessing attributes on this proxy will raise a
``RuntimeError``.
.. versionadded:: 0.9
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:

View file

@ -136,14 +136,6 @@ local from ``get_db()``::
Accessing ``db`` will call ``get_db`` internally, in the same way that
:data:`current_app` works.
----
If you're writing an extension, :data:`g` should be reserved for user
code. You may store internal data on the context itself, but be sure to
use a sufficiently unique name. The current context is accessed with
:data:`_app_ctx_stack.top <_app_ctx_stack>`. For more information see
:doc:`/extensiondev`.
Events and Signals
------------------

View file

@ -187,12 +187,6 @@ when the application context ends. If it should only be valid during a
request, or would not be used in the CLI outside a reqeust, use
:meth:`~flask.Flask.teardown_request`.
An older technique for storing context data was to store it on
``_app_ctx_stack.top`` or ``_request_ctx_stack.top``. However, this just
moves the same namespace collision problem elsewhere (although less
likely) and modifies objects that are very internal to Flask's
operations. Prefer storing data under a unique name in ``g``.
Views and Models
----------------

View file

@ -30,10 +30,6 @@ or create an application context itself. At that point the ``get_db``
function can be used to get the current database connection. Whenever the
context is destroyed the database connection will be terminated.
Note: if you use Flask 0.9 or older you need to use
``flask._app_ctx_stack.top`` instead of ``g`` as the :data:`flask.g`
object was bound to the request and not application context.
Example::
@app.route('/')

View file

@ -37,12 +37,14 @@ context, which also pushes an :doc:`app context </appcontext>`. When the
request ends it pops the request context then the application context.
The context is unique to each thread (or other worker type).
:data:`request` cannot be passed to another thread, the other thread
will have a different context stack and will not know about the request
the parent thread was pointing to.
:data:`request` cannot be passed to another thread, the other thread has
a different context space and will not know about the request the parent
thread was pointing to.
Context locals are implemented in Werkzeug. See :doc:`werkzeug:local`
for more information on how this works internally.
Context locals are implemented using Python's :mod:`contextvars` and
Werkzeug's :class:`~werkzeug.local.LocalProxy`. Python manages the
lifetime of context vars automatically, and local proxy wraps that
low-level interface to make the data easier to work with.
Manually Push a Context
@ -87,10 +89,9 @@ How the Context Works
The :meth:`Flask.wsgi_app` method is called to handle each request. It
manages the contexts during the request. Internally, the request and
application contexts work as stacks, :data:`_request_ctx_stack` and
:data:`_app_ctx_stack`. When contexts are pushed onto the stack, the
application contexts work like stacks. When contexts are pushed, the
proxies that depend on them are available and point at information from
the top context on the stack.
the top item.
When the request starts, a :class:`~ctx.RequestContext` is created and
pushed, which creates and pushes an :class:`~ctx.AppContext` first if
@ -99,10 +100,10 @@ these contexts are pushed, the :data:`current_app`, :data:`g`,
:data:`request`, and :data:`session` proxies are available to the
original thread handling the request.
Because the contexts are stacks, other contexts may be pushed to change
the proxies during a request. While this is not a common pattern, it
can be used in advanced applications to, for example, do internal
redirects or chain different applications together.
Other contexts may be pushed to change the proxies during a request.
While this is not a common pattern, it can be used in advanced
applications to, for example, do internal redirects or chain different
applications together.
After the request is dispatched and a response is generated and sent,
the request context is popped, which then pops the application context.

View file

@ -1284,29 +1284,30 @@ class Flask(Scaffold):
@setupmethod
def teardown_appcontext(self, f: T_teardown) -> T_teardown:
"""Registers a function to be called when the application context
ends. These functions are typically also called when the request
context is popped.
"""Registers a function to be called when the application
context is popped. The application context is typically popped
after the request context for each request, at the end of CLI
commands, or after a manually pushed context ends.
Example::
.. code-block:: python
ctx = app.app_context()
ctx.push()
...
ctx.pop()
with app.app_context():
...
When ``ctx.pop()`` is executed in the above example, the teardown
functions are called just before the app context moves from the
stack of active contexts. This becomes relevant if you are using
such constructs in tests.
When the ``with`` block exits (or ``ctx.pop()`` is called), the
teardown functions are called just before the app context is
made inactive. Since a request context typically also manages an
application context it would also be called when you pop a
request context.
Since a request context typically also manages an application
context it would also be called when you pop a request context.
When a teardown function was called because of an unhandled
exception it will be passed an error object. If an
:meth:`errorhandler` is registered, it will handle the exception
and the teardown will not receive it.
When a teardown function was called because of an unhandled exception
it will be passed an error object. If an :meth:`errorhandler` is
registered, it will handle the exception and the teardown will not
receive it.
Teardown functions must avoid raising exceptions. If they
execute code that might fail they must surround that code with a
``try``/``except`` block and log any errors.
The return values of teardown functions are ignored.

View file

@ -227,12 +227,10 @@ def has_app_context() -> bool:
class AppContext:
"""The application context binds an application object implicitly
to the current thread or greenlet, similar to how the
:class:`RequestContext` binds request information. The application
context is also implicitly created if a request context is created
but the application is not on top of the individual application
context.
"""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.
"""
def __init__(self, app: "Flask") -> None:
@ -278,10 +276,10 @@ class AppContext:
class RequestContext:
"""The request context contains all request relevant information. It is
created at the beginning of the request and pushed to the
`_request_ctx_stack` and removed at the end of it. It will create the
URL adapter and request object for the WSGI environment provided.
"""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
:meth:`~flask.Flask.test_request_context` and

View file

@ -574,30 +574,27 @@ class Scaffold:
@setupmethod
def teardown_request(self, f: T_teardown) -> T_teardown:
"""Register a function to be run at the end of each request,
regardless of whether there was an exception or not. These functions
are executed when the request context is popped, even if not an
actual request was performed.
"""Register a function to be called when the request context is
popped. Typically this happens at the end of each request, but
contexts may be pushed manually as well during testing.
Example::
.. code-block:: python
ctx = app.test_request_context()
ctx.push()
...
ctx.pop()
with app.test_request_context():
...
When ``ctx.pop()`` is executed in the above example, the teardown
functions are called just before the request context moves from the
stack of active contexts. This becomes relevant if you are using
such constructs in tests.
When the ``with`` block exits (or ``ctx.pop()`` is called), the
teardown functions are called just before the request context is
made inactive.
Teardown functions must avoid raising exceptions. If
they execute code that might fail they
will have to surround the execution of that code with try/except
statements and log any errors.
When a teardown function was called because of an unhandled
exception it will be passed an error object. If an
:meth:`errorhandler` is registered, it will handle the exception
and the teardown will not receive it.
When a teardown function was called because of an exception it will
be passed an error object.
Teardown functions must avoid raising exceptions. If they
execute code that might fail they must surround that code with a
``try``/``except`` block and log any errors.
The return values of teardown functions are ignored.
"""

View file

@ -94,11 +94,10 @@ class EnvironBuilder(werkzeug.test.EnvironBuilder):
class FlaskClient(Client):
"""Works like a regular Werkzeug test client but has some knowledge about
how Flask works to defer the cleanup of the request context stack to the
end of a ``with`` body when used in a ``with`` statement. For general
information about how to use this class refer to
:class:`werkzeug.test.Client`.
"""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 :class:`werkzeug.test.Client`.
.. versionchanged:: 0.12
`app.test_client()` includes preset default environment, which can be