[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 99400930ac1d4e5e10a5ae30f8202d8bc2661e39)

Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 3c931a7..5c56c41 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -260,19 +260,33 @@
       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
@@ -306,6 +320,14 @@
       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 @@
    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')
-        var.set('spam')
+      .. testcode::
 
-        def main():
-            # 'var' was set to 'spam' before
-            # calling 'copy_context()' and 'ctx.run(main)', so:
-            # var.get() == ctx[var] == 'spam'
+         import contextvars
 
-            var.set('ham')
+         var = contextvars.ContextVar('var')
+         var.set('spam')
+         print(var.get())  # 'spam'
 
-            # Now, after setting 'var' to 'ham':
-            # var.get() == ctx[var] == 'ham'
+         ctx = contextvars.copy_context()
 
-        ctx = copy_context()
+         def main():
+             # 'var' was set to 'spam' before
+             # calling 'copy_context()' and 'ctx.run(main)', so:
+             print(var.get())  # 'spam'
+             print(ctx[var])  # 'spam'
 
-        # Any changes that the 'main' function makes to 'var'
-        # will be contained in 'ctx'.
-        ctx.run(main)
+             var.set('ham')
 
-        # The 'main()' function was run in the 'ctx' context,
-        # so changes to 'var' are contained in it:
-        # ctx[var] == 'ham'
+             # Now, after setting 'var' to 'ham':
+             print(var.get())  # 'ham'
+             print(ctx[var])  # 'ham'
 
-        # However, outside of 'ctx', 'var' is still set to 'spam':
-        # var.get() == 'spam'
+         # Any changes that the 'main' function makes to 'var'
+         # will be contained in 'ctx'.
+         ctx.run(main)
 
-      The method raises a :exc:`RuntimeError` when called on the same
-      context object from more than one OS thread, or when called
-      recursively.
+         # The 'main()' function was run in the 'ctx' context,
+         # so changes to 'var' are contained in it:
+         print(ctx[var])  # 'ham'
+
+         # However, outside of 'ctx', 'var' is still set to 'spam':
+         print(var.get())  # 'spam'
+
+      .. testoutput::
+         :hide:
+
+         spam
+         spam
+         spam
+         ham
+         ham
+         ham
+         spam
 
    .. method:: copy()
 
diff --git a/Misc/NEWS.d/next/Documentation/2024-10-10-02-56-24.gh-issue-124872.0mDDOq.rst b/Misc/NEWS.d/next/Documentation/2024-10-10-02-56-24.gh-issue-124872.0mDDOq.rst
new file mode 100644
index 0000000..69a5c76
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2024-10-10-02-56-24.gh-issue-124872.0mDDOq.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`.