mirror of https://github.com/python/cpython
[3.13] gh-124872: Refine contextvars documentation (GH-124773) (#125233)
[3.13] gh-124872: Refine contextvars documentation
* Add definitions for "context", "current context", and "context
management protocol".
* Update related definitions to be consistent with the new
definitions.
* Restructure the documentation for the `contextvars.Context` class
to prepare for adding context manager support, and for consistency
with the definitions.
* Use `testcode` and `testoutput` to test the `Context.run` example.
(cherry-picked from commit 99400930ac
)
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
This commit is contained in:
parent
5f4218418b
commit
2db2b5ea9c
|
@ -260,19 +260,33 @@ Glossary
|
|||
advanced mathematical feature. If you're not aware of a need for them,
|
||||
it's almost certain you can safely ignore them.
|
||||
|
||||
context
|
||||
This term has different meanings depending on where and how it is used.
|
||||
Some common meanings:
|
||||
|
||||
* The temporary state or environment established by a :term:`context
|
||||
manager` via a :keyword:`with` statement.
|
||||
* The collection of keyvalue bindings associated with a particular
|
||||
:class:`contextvars.Context` object and accessed via
|
||||
:class:`~contextvars.ContextVar` objects. Also see :term:`context
|
||||
variable`.
|
||||
* A :class:`contextvars.Context` object. Also see :term:`current
|
||||
context`.
|
||||
|
||||
context management protocol
|
||||
The :meth:`~object.__enter__` and :meth:`~object.__exit__` methods called
|
||||
by the :keyword:`with` statement. See :pep:`343`.
|
||||
|
||||
context manager
|
||||
An object which controls the environment seen in a :keyword:`with`
|
||||
statement by defining :meth:`~object.__enter__` and :meth:`~object.__exit__` methods.
|
||||
See :pep:`343`.
|
||||
An object which implements the :term:`context management protocol` and
|
||||
controls the environment seen in a :keyword:`with` statement. See
|
||||
:pep:`343`.
|
||||
|
||||
context variable
|
||||
A variable which can have different values depending on its context.
|
||||
This is similar to Thread-Local Storage in which each execution
|
||||
thread may have a different value for a variable. However, with context
|
||||
variables, there may be several contexts in one execution thread and the
|
||||
main usage for context variables is to keep track of variables in
|
||||
A variable whose value depends on which context is the :term:`current
|
||||
context`. Values are accessed via :class:`contextvars.ContextVar`
|
||||
objects. Context variables are primarily used to isolate state between
|
||||
concurrent asynchronous tasks.
|
||||
See :mod:`contextvars`.
|
||||
|
||||
contiguous
|
||||
.. index:: C-contiguous, Fortran contiguous
|
||||
|
@ -306,6 +320,14 @@ Glossary
|
|||
is used when necessary to distinguish this implementation from others
|
||||
such as Jython or IronPython.
|
||||
|
||||
current context
|
||||
The :term:`context` (:class:`contextvars.Context` object) that is
|
||||
currently used by :class:`~contextvars.ContextVar` objects to access (get
|
||||
or set) the values of :term:`context variables <context variable>`. Each
|
||||
thread has its own current context. Frameworks for executing asynchronous
|
||||
tasks (see :mod:`asyncio`) associate each task with a context which
|
||||
becomes the current context whenever the task starts or resumes execution.
|
||||
|
||||
decorator
|
||||
A function returning another function, usually applied as a function
|
||||
transformation using the ``@wrapper`` syntax. Common examples for
|
||||
|
|
|
@ -144,36 +144,67 @@ Manual Context Management
|
|||
To get a copy of the current context use the
|
||||
:func:`~contextvars.copy_context` function.
|
||||
|
||||
Every thread will have a different top-level :class:`~contextvars.Context`
|
||||
object. This means that a :class:`ContextVar` object behaves in a similar
|
||||
fashion to :func:`threading.local` when values are assigned in different
|
||||
threads.
|
||||
Each thread has its own effective stack of :class:`!Context` objects. The
|
||||
:term:`current context` is the :class:`!Context` object at the top of the
|
||||
current thread's stack. All :class:`!Context` objects in the stacks are
|
||||
considered to be *entered*.
|
||||
|
||||
*Entering* a context, which can be done by calling its :meth:`~Context.run`
|
||||
method, makes the context the current context by pushing it onto the top of
|
||||
the current thread's context stack.
|
||||
|
||||
*Exiting* from the current context, which can be done by returning from the
|
||||
callback passed to the :meth:`~Context.run` method, restores the current
|
||||
context to what it was before the context was entered by popping the context
|
||||
off the top of the context stack.
|
||||
|
||||
Since each thread has its own context stack, :class:`ContextVar` objects
|
||||
behave in a similar fashion to :func:`threading.local` when values are
|
||||
assigned in different threads.
|
||||
|
||||
Attempting to enter an already entered context, including contexts entered in
|
||||
other threads, raises a :exc:`RuntimeError`.
|
||||
|
||||
After exiting a context, it can later be re-entered (from any thread).
|
||||
|
||||
Any changes to :class:`ContextVar` values via the :meth:`ContextVar.set`
|
||||
method are recorded in the current context. The :meth:`ContextVar.get`
|
||||
method returns the value associated with the current context. Exiting a
|
||||
context effectively reverts any changes made to context variables while the
|
||||
context was entered (if needed, the values can be restored by re-entering the
|
||||
context).
|
||||
|
||||
Context implements the :class:`collections.abc.Mapping` interface.
|
||||
|
||||
.. method:: run(callable, *args, **kwargs)
|
||||
|
||||
Execute ``callable(*args, **kwargs)`` code in the context object
|
||||
the *run* method is called on. Return the result of the execution
|
||||
or propagate an exception if one occurred.
|
||||
Enters the Context, executes ``callable(*args, **kwargs)``, then exits the
|
||||
Context. Returns *callable*'s return value, or propagates an exception if
|
||||
one occurred.
|
||||
|
||||
Any changes to any context variables that *callable* makes will
|
||||
be contained in the context object::
|
||||
Example:
|
||||
|
||||
var = ContextVar('var')
|
||||
.. testcode::
|
||||
|
||||
import contextvars
|
||||
|
||||
var = contextvars.ContextVar('var')
|
||||
var.set('spam')
|
||||
print(var.get()) # 'spam'
|
||||
|
||||
ctx = contextvars.copy_context()
|
||||
|
||||
def main():
|
||||
# 'var' was set to 'spam' before
|
||||
# calling 'copy_context()' and 'ctx.run(main)', so:
|
||||
# var.get() == ctx[var] == 'spam'
|
||||
print(var.get()) # 'spam'
|
||||
print(ctx[var]) # 'spam'
|
||||
|
||||
var.set('ham')
|
||||
|
||||
# Now, after setting 'var' to 'ham':
|
||||
# var.get() == ctx[var] == 'ham'
|
||||
|
||||
ctx = copy_context()
|
||||
print(var.get()) # 'ham'
|
||||
print(ctx[var]) # 'ham'
|
||||
|
||||
# Any changes that the 'main' function makes to 'var'
|
||||
# will be contained in 'ctx'.
|
||||
|
@ -181,14 +212,21 @@ Manual Context Management
|
|||
|
||||
# The 'main()' function was run in the 'ctx' context,
|
||||
# so changes to 'var' are contained in it:
|
||||
# ctx[var] == 'ham'
|
||||
print(ctx[var]) # 'ham'
|
||||
|
||||
# However, outside of 'ctx', 'var' is still set to 'spam':
|
||||
# var.get() == 'spam'
|
||||
print(var.get()) # 'spam'
|
||||
|
||||
The method raises a :exc:`RuntimeError` when called on the same
|
||||
context object from more than one OS thread, or when called
|
||||
recursively.
|
||||
.. testoutput::
|
||||
:hide:
|
||||
|
||||
spam
|
||||
spam
|
||||
spam
|
||||
ham
|
||||
ham
|
||||
ham
|
||||
spam
|
||||
|
||||
.. method:: copy()
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Added definitions for :term:`context`, :term:`current context`, and
|
||||
:term:`context management protocol`, updated related definitions to be
|
||||
consistent, and expanded the documentation for :class:`contextvars.Context`.
|
Loading…
Reference in New Issue