Skip to content

Commit e0dad45

Browse files
committed
update docs about contexts
1 parent 82c2e03 commit e0dad45

File tree

9 files changed

+82
-132
lines changed

9 files changed

+82
-132
lines changed

docs/api.rst

+14-42
Original file line numberDiff line numberDiff line change
@@ -311,56 +311,28 @@ Useful Internals
311311
.. autoclass:: flask.ctx.RequestContext
312312
:members:
313313

314-
.. data:: _request_ctx_stack
314+
.. data:: flask.globals.request_ctx
315315

316-
The internal :class:`~werkzeug.local.LocalStack` that holds
317-
:class:`~flask.ctx.RequestContext` instances. Typically, the
318-
:data:`request` and :data:`session` proxies should be accessed
319-
instead of the stack. It may be useful to access the stack in
320-
extension code.
316+
The current :class:`~flask.ctx.RequestContext`. If a request context
317+
is not active, accessing attributes on this proxy will raise a
318+
``RuntimeError``.
321319

322-
The following attributes are always present on each layer of the
323-
stack:
324-
325-
`app`
326-
the active Flask application.
327-
328-
`url_adapter`
329-
the URL adapter that was used to match the request.
330-
331-
`request`
332-
the current request object.
333-
334-
`session`
335-
the active session object.
336-
337-
`g`
338-
an object with all the attributes of the :data:`flask.g` object.
339-
340-
`flashes`
341-
an internal cache for the flashed messages.
342-
343-
Example usage::
344-
345-
from flask import _request_ctx_stack
346-
347-
def get_session():
348-
ctx = _request_ctx_stack.top
349-
if ctx is not None:
350-
return ctx.session
320+
This is an internal object that is essential to how Flask handles
321+
requests. Accessing this should not be needed in most cases. Most
322+
likely you want :data:`request` and :data:`session` instead.
351323

352324
.. autoclass:: flask.ctx.AppContext
353325
:members:
354326

355-
.. data:: _app_ctx_stack
327+
.. data:: flask.globals.app_ctx
356328

357-
The internal :class:`~werkzeug.local.LocalStack` that holds
358-
:class:`~flask.ctx.AppContext` instances. Typically, the
359-
:data:`current_app` and :data:`g` proxies should be accessed instead
360-
of the stack. Extensions can access the contexts on the stack as a
361-
namespace to store data.
329+
The current :class:`~flask.ctx.AppContext`. If an app context is not
330+
active, accessing attributes on this proxy will raise a
331+
``RuntimeError``.
362332

363-
.. versionadded:: 0.9
333+
This is an internal object that is essential to how Flask handles
334+
requests. Accessing this should not be needed in most cases. Most
335+
likely you want :data:`current_app` and :data:`g` instead.
364336

365337
.. autoclass:: flask.blueprints.BlueprintSetupState
366338
:members:

docs/appcontext.rst

-8
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,6 @@ local from ``get_db()``::
136136
Accessing ``db`` will call ``get_db`` internally, in the same way that
137137
:data:`current_app` works.
138138

139-
----
140-
141-
If you're writing an extension, :data:`g` should be reserved for user
142-
code. You may store internal data on the context itself, but be sure to
143-
use a sufficiently unique name. The current context is accessed with
144-
:data:`_app_ctx_stack.top <_app_ctx_stack>`. For more information see
145-
:doc:`/extensiondev`.
146-
147139

148140
Events and Signals
149141
------------------

docs/extensiondev.rst

-6
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,6 @@ when the application context ends. If it should only be valid during a
187187
request, or would not be used in the CLI outside a reqeust, use
188188
:meth:`~flask.Flask.teardown_request`.
189189

190-
An older technique for storing context data was to store it on
191-
``_app_ctx_stack.top`` or ``_request_ctx_stack.top``. However, this just
192-
moves the same namespace collision problem elsewhere (although less
193-
likely) and modifies objects that are very internal to Flask's
194-
operations. Prefer storing data under a unique name in ``g``.
195-
196190

197191
Views and Models
198192
----------------

docs/patterns/sqlite3.rst

-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ or create an application context itself. At that point the ``get_db``
3030
function can be used to get the current database connection. Whenever the
3131
context is destroyed the database connection will be terminated.
3232

33-
Note: if you use Flask 0.9 or older you need to use
34-
``flask._app_ctx_stack.top`` instead of ``g`` as the :data:`flask.g`
35-
object was bound to the request and not application context.
36-
3733
Example::
3834

3935
@app.route('/')

docs/reqcontext.rst

+13-12
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ context, which also pushes an :doc:`app context </appcontext>`. When the
3737
request ends it pops the request context then the application context.
3838

3939
The context is unique to each thread (or other worker type).
40-
:data:`request` cannot be passed to another thread, the other thread
41-
will have a different context stack and will not know about the request
42-
the parent thread was pointing to.
40+
:data:`request` cannot be passed to another thread, the other thread has
41+
a different context space and will not know about the request the parent
42+
thread was pointing to.
4343

44-
Context locals are implemented in Werkzeug. See :doc:`werkzeug:local`
45-
for more information on how this works internally.
44+
Context locals are implemented using Python's :mod:`contextvars` and
45+
Werkzeug's :class:`~werkzeug.local.LocalProxy`. Python manages the
46+
lifetime of context vars automatically, and local proxy wraps that
47+
low-level interface to make the data easier to work with.
4648

4749

4850
Manually Push a Context
@@ -87,10 +89,9 @@ How the Context Works
8789

8890
The :meth:`Flask.wsgi_app` method is called to handle each request. It
8991
manages the contexts during the request. Internally, the request and
90-
application contexts work as stacks, :data:`_request_ctx_stack` and
91-
:data:`_app_ctx_stack`. When contexts are pushed onto the stack, the
92+
application contexts work like stacks. When contexts are pushed, the
9293
proxies that depend on them are available and point at information from
93-
the top context on the stack.
94+
the top item.
9495

9596
When the request starts, a :class:`~ctx.RequestContext` is created and
9697
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`,
99100
:data:`request`, and :data:`session` proxies are available to the
100101
original thread handling the request.
101102

102-
Because the contexts are stacks, other contexts may be pushed to change
103-
the proxies during a request. While this is not a common pattern, it
104-
can be used in advanced applications to, for example, do internal
105-
redirects or chain different applications together.
103+
Other contexts may be pushed to change the proxies during a request.
104+
While this is not a common pattern, it can be used in advanced
105+
applications to, for example, do internal redirects or chain different
106+
applications together.
106107

107108
After the request is dispatched and a response is generated and sent,
108109
the request context is popped, which then pops the application context.

src/flask/app.py

+22-21
Original file line numberDiff line numberDiff line change
@@ -1284,29 +1284,30 @@ def before_first_request(self, f: T_before_first_request) -> T_before_first_requ
12841284

12851285
@setupmethod
12861286
def teardown_appcontext(self, f: T_teardown) -> T_teardown:
1287-
"""Registers a function to be called when the application context
1288-
ends. These functions are typically also called when the request
1289-
context is popped.
1287+
"""Registers a function to be called when the application
1288+
context is popped. The application context is typically popped
1289+
after the request context for each request, at the end of CLI
1290+
commands, or after a manually pushed context ends.
12901291
1291-
Example::
1292-
1293-
ctx = app.app_context()
1294-
ctx.push()
1295-
...
1296-
ctx.pop()
1297-
1298-
When ``ctx.pop()`` is executed in the above example, the teardown
1299-
functions are called just before the app context moves from the
1300-
stack of active contexts. This becomes relevant if you are using
1301-
such constructs in tests.
1302-
1303-
Since a request context typically also manages an application
1304-
context it would also be called when you pop a request context.
1292+
.. code-block:: python
13051293
1306-
When a teardown function was called because of an unhandled exception
1307-
it will be passed an error object. If an :meth:`errorhandler` is
1308-
registered, it will handle the exception and the teardown will not
1309-
receive it.
1294+
with app.app_context():
1295+
...
1296+
1297+
When the ``with`` block exits (or ``ctx.pop()`` is called), the
1298+
teardown functions are called just before the app context is
1299+
made inactive. Since a request context typically also manages an
1300+
application context it would also be called when you pop a
1301+
request context.
1302+
1303+
When a teardown function was called because of an unhandled
1304+
exception it will be passed an error object. If an
1305+
:meth:`errorhandler` is registered, it will handle the exception
1306+
and the teardown will not receive it.
1307+
1308+
Teardown functions must avoid raising exceptions. If they
1309+
execute code that might fail they must surround that code with a
1310+
``try``/``except`` block and log any errors.
13101311
13111312
The return values of teardown functions are ignored.
13121313

src/flask/ctx.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,10 @@ def has_app_context() -> bool:
227227

228228

229229
class AppContext:
230-
"""The application context binds an application object implicitly
231-
to the current thread or greenlet, similar to how the
232-
:class:`RequestContext` binds request information. The application
233-
context is also implicitly created if a request context is created
234-
but the application is not on top of the individual application
235-
context.
230+
"""The app context contains application-specific information. An app
231+
context is created and pushed at the beginning of each request if
232+
one is not already active. An app context is also pushed when
233+
running CLI commands.
236234
"""
237235

238236
def __init__(self, app: "Flask") -> None:
@@ -278,10 +276,10 @@ def __exit__(
278276

279277

280278
class RequestContext:
281-
"""The request context contains all request relevant information. It is
282-
created at the beginning of the request and pushed to the
283-
`_request_ctx_stack` and removed at the end of it. It will create the
284-
URL adapter and request object for the WSGI environment provided.
279+
"""The request context contains per-request information. The Flask
280+
app creates and pushes it at the beginning of the request, then pops
281+
it at the end of the request. It will create the URL adapter and
282+
request object for the WSGI environment provided.
285283
286284
Do not attempt to use this class directly, instead use
287285
:meth:`~flask.Flask.test_request_context` and

src/flask/scaffold.py

+21-24
Original file line numberDiff line numberDiff line change
@@ -574,30 +574,27 @@ def after_request(self, f: T_after_request) -> T_after_request:
574574

575575
@setupmethod
576576
def teardown_request(self, f: T_teardown) -> T_teardown:
577-
"""Register a function to be run at the end of each request,
578-
regardless of whether there was an exception or not. These functions
579-
are executed when the request context is popped, even if not an
580-
actual request was performed.
581-
582-
Example::
583-
584-
ctx = app.test_request_context()
585-
ctx.push()
586-
...
587-
ctx.pop()
588-
589-
When ``ctx.pop()`` is executed in the above example, the teardown
590-
functions are called just before the request context moves from the
591-
stack of active contexts. This becomes relevant if you are using
592-
such constructs in tests.
593-
594-
Teardown functions must avoid raising exceptions. If
595-
they execute code that might fail they
596-
will have to surround the execution of that code with try/except
597-
statements and log any errors.
598-
599-
When a teardown function was called because of an exception it will
600-
be passed an error object.
577+
"""Register a function to be called when the request context is
578+
popped. Typically this happens at the end of each request, but
579+
contexts may be pushed manually as well during testing.
580+
581+
.. code-block:: python
582+
583+
with app.test_request_context():
584+
...
585+
586+
When the ``with`` block exits (or ``ctx.pop()`` is called), the
587+
teardown functions are called just before the request context is
588+
made inactive.
589+
590+
When a teardown function was called because of an unhandled
591+
exception it will be passed an error object. If an
592+
:meth:`errorhandler` is registered, it will handle the exception
593+
and the teardown will not receive it.
594+
595+
Teardown functions must avoid raising exceptions. If they
596+
execute code that might fail they must surround that code with a
597+
``try``/``except`` block and log any errors.
601598
602599
The return values of teardown functions are ignored.
603600
"""

src/flask/testing.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,10 @@ def json_dumps(self, obj: t.Any, **kwargs: t.Any) -> str: # type: ignore
9494

9595

9696
class FlaskClient(Client):
97-
"""Works like a regular Werkzeug test client but has some knowledge about
98-
how Flask works to defer the cleanup of the request context stack to the
99-
end of a ``with`` body when used in a ``with`` statement. For general
100-
information about how to use this class refer to
101-
:class:`werkzeug.test.Client`.
97+
"""Works like a regular Werkzeug test client but has knowledge about
98+
Flask's contexts to defer the cleanup of the request context until
99+
the end of a ``with`` block. For general information about how to
100+
use this class refer to :class:`werkzeug.test.Client`.
102101
103102
.. versionchanged:: 0.12
104103
`app.test_client()` includes preset default environment, which can be

0 commit comments

Comments
 (0)