summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/contextvars.rst20
-rw-r--r--Doc/glossary.rst40
-rw-r--r--Doc/library/contextvars.rst98
-rw-r--r--Include/cpython/context.h23
-rw-r--r--Misc/NEWS.d/next/Documentation/2024-09-29-18-14-52.gh-issue-119333.7tinr0.rst3
5 files changed, 132 insertions, 52 deletions
diff --git a/Doc/c-api/contextvars.rst b/Doc/c-api/contextvars.rst
index 0de135b..59e74ba 100644
--- a/Doc/c-api/contextvars.rst
+++ b/Doc/c-api/contextvars.rst
@@ -122,18 +122,24 @@ Context object management functions:
.. c:type:: PyContextEvent
Enumeration of possible context object watcher events:
- - ``Py_CONTEXT_EVENT_ENTER``
- - ``Py_CONTEXT_EVENT_EXIT``
+
+ - ``Py_CONTEXT_EVENT_ENTER``: A context has been entered, causing the
+ :term:`current context` to switch to it. The object passed to the watch
+ callback is the now-current :class:`contextvars.Context` object. Each
+ enter event will eventually have a corresponding exit event for the same
+ context object after any subsequently entered contexts have themselves been
+ exited.
+ - ``Py_CONTEXT_EVENT_EXIT``: A context is about to be exited, which will
+ cause the :term:`current context` to switch back to what it was before the
+ context was entered. The object passed to the watch callback is the
+ still-current :class:`contextvars.Context` object.
.. versionadded:: 3.14
.. c:type:: int (*PyContext_WatchCallback)(PyContextEvent event, PyContext* ctx)
- Type of a context object watcher callback function.
- If *event* is ``Py_CONTEXT_EVENT_ENTER``, then the callback is invoked
- after *ctx* has been set as the current context for the current thread.
- Otherwise, the callback is invoked before the deactivation of *ctx* as the current context
- and the restoration of the previous contex object for the current thread.
+ Context object watcher callback function. The object passed to the callback
+ is event-specific; see :c:type:`PyContextEvent` for details.
If the callback returns with an exception set, it must return ``-1``; this
exception will be printed as an unraisable exception using
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index cb7e0a2b..1d40773 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -265,19 +265,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 key­value 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
@@ -311,6 +325,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
diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst
index 2a79dfe..2b1fb9f 100644
--- a/Doc/library/contextvars.rst
+++ b/Doc/library/contextvars.rst
@@ -144,51 +144,89 @@ 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.
+
+ Example:
+
+ .. testcode::
+
+ import contextvars
- Any changes to any context variables that *callable* makes will
- be contained in the context object::
+ var = contextvars.ContextVar('var')
+ var.set('spam')
+ print(var.get()) # 'spam'
- var = ContextVar('var')
- var.set('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'
+ def main():
+ # 'var' was set to 'spam' before
+ # calling 'copy_context()' and 'ctx.run(main)', so:
+ print(var.get()) # 'spam'
+ print(ctx[var]) # 'spam'
- var.set('ham')
+ var.set('ham')
- # Now, after setting 'var' to 'ham':
- # var.get() == ctx[var] == 'ham'
+ # Now, after setting 'var' to 'ham':
+ print(var.get()) # 'ham'
+ print(ctx[var]) # 'ham'
- ctx = copy_context()
+ # Any changes that the 'main' function makes to 'var'
+ # will be contained in 'ctx'.
+ ctx.run(main)
- # Any changes that the 'main' function makes to 'var'
- # will be contained in 'ctx'.
- ctx.run(main)
+ # The 'main()' function was run in the 'ctx' context,
+ # so changes to 'var' are contained in it:
+ print(ctx[var]) # 'ham'
- # The 'main()' function was run in the 'ctx' context,
- # so changes to 'var' are contained in it:
- # ctx[var] == 'ham'
+ # However, outside of 'ctx', 'var' is still set to 'spam':
+ print(var.get()) # 'spam'
- # However, outside of 'ctx', 'var' is still set to 'spam':
- # var.get() == 'spam'
+ .. testoutput::
+ :hide:
- The method raises a :exc:`RuntimeError` when called on the same
- context object from more than one OS thread, or when called
- recursively.
+ spam
+ spam
+ spam
+ ham
+ ham
+ ham
+ spam
.. method:: copy()
diff --git a/Include/cpython/context.h b/Include/cpython/context.h
index ec72966..d722b4d 100644
--- a/Include/cpython/context.h
+++ b/Include/cpython/context.h
@@ -28,15 +28,26 @@ PyAPI_FUNC(int) PyContext_Enter(PyObject *);
PyAPI_FUNC(int) PyContext_Exit(PyObject *);
typedef enum {
- Py_CONTEXT_EVENT_ENTER,
- Py_CONTEXT_EVENT_EXIT,
+ /*
+ * A context has been entered, causing the "current context" to switch to
+ * it. The object passed to the watch callback is the now-current
+ * contextvars.Context object. Each enter event will eventually have a
+ * corresponding exit event for the same context object after any
+ * subsequently entered contexts have themselves been exited.
+ */
+ Py_CONTEXT_EVENT_ENTER,
+ /*
+ * A context is about to be exited, which will cause the "current context"
+ * to switch back to what it was before the context was entered. The
+ * object passed to the watch callback is the still-current
+ * contextvars.Context object.
+ */
+ Py_CONTEXT_EVENT_EXIT,
} PyContextEvent;
/*
- * Callback to be invoked when a context object is entered or exited.
- *
- * The callback is invoked with the event and a reference to
- * the context after its entered and before its exited.
+ * Context object watcher callback function. The object passed to the callback
+ * is event-specific; see PyContextEvent for details.
*
* if the callback returns with an exception set, it must return -1. Otherwise
* it should return 0
diff --git a/Misc/NEWS.d/next/Documentation/2024-09-29-18-14-52.gh-issue-119333.7tinr0.rst b/Misc/NEWS.d/next/Documentation/2024-09-29-18-14-52.gh-issue-119333.7tinr0.rst
new file mode 100644
index 0000000..69a5c76
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2024-09-29-18-14-52.gh-issue-119333.7tinr0.rst
@@ -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`.