@@ -144,21 +144,90 @@ Manual Context Management
144144 To get a copy of the current context use the
145145 :func: `~contextvars.copy_context ` function.
146146
147- Every thread will have a different top-level :class: `~contextvars.Context `
148- object. This means that a :class: `ContextVar ` object behaves in a similar
149- fashion to :func: `threading.local ` when values are assigned in different
150- threads.
147+ Each thread has its own effective stack of :class: `!Context ` objects. The
148+ *current context * is the :class: `!Context ` object at the top of the current
149+ thread's stack. All :class: `!Context ` objects in the stacks are considered
150+ to be *entered *.
151+
152+ *Entering * a context, either by calling the :meth: `~Context.run ` method or
153+ using the context as a :term: `context manager `, pushes the context onto the
154+ top of the current thread's stack, making it the current context.
155+
156+ *Exiting * from the current context, either by returning from the callback
157+ passed to :meth: `~Context.run ` or by exiting the :keyword: `with ` statement
158+ suite, pops the context off of the top of the stack, restoring the current
159+ context to what it was before.
160+
161+ Since each thread has its own context stack, :class: `ContextVar ` objects
162+ behave in a similar fashion to :func: `threading.local ` when values are
163+ assigned in different threads.
164+
165+ Attempting to do either of the following raises a :exc: `RuntimeError `:
166+
167+ * Entering an already entered context, including contexts entered in
168+ other threads.
169+ * Exiting from a context that is not the current context.
170+
171+ After exiting a context, it can later be re-entered (from any thread).
172+
173+ Any changes to :class: `ContextVar ` values via the :meth: `ContextVar.set `
174+ method are recorded in the current context. The :meth: `ContextVar.get `
175+ method returns the value associated with the current context. Exiting a
176+ context effectively reverts any changes made to context variables while the
177+ context was entered (if needed, the values can be restored by re-entering the
178+ context).
151179
152180 Context implements the :class: `collections.abc.Mapping ` interface.
153181
154- .. method :: run(callable, *args, **kwargs)
182+ .. versionadded :: 3.14
183+ Added support for the :term: `context management protocol `.
184+
185+ When used as a :term: `context manager `, the value bound to the identifier
186+ given in the :keyword: `with ` statement's :keyword: `!as ` clause (if present)
187+ is the :class: `!Context ` object itself.
188+
189+ Example:
155190
156- Execute ``callable(*args, **kwargs) `` code in the context object
157- the *run * method is called on. Return the result of the execution
158- or propagate an exception if one occurred.
191+ .. testcode ::
159192
160- Any changes to any context variables that *callable * makes will
161- be contained in the context object.
193+ import contextvars
194+
195+ var = contextvars.ContextVar("var")
196+ var.set("initial")
197+ print(var.get()) # 'initial'
198+
199+ # Copy the current Context and enter the copy.
200+ with contextvars.copy_context() as ctx:
201+ var.set("updated")
202+ print(var in ctx) # 'True'
203+ print(ctx[var]) # 'updated'
204+ print(var.get()) # 'updated'
205+
206+ # Exited ctx, so the observed value of var has reverted.
207+ print(var.get()) # 'initial'
208+ # But the updated value is still recorded in ctx.
209+ print(ctx[var]) # 'updated'
210+
211+ # Re-entering ctx restores the updated value of var.
212+ with ctx:
213+ print(var.get()) # 'updated'
214+
215+ .. testoutput ::
216+ :hide:
217+
218+ initial
219+ True
220+ updated
221+ updated
222+ initial
223+ updated
224+ updated
225+
226+ .. method :: run(callable, *args, **kwargs)
227+
228+ Enters the Context, executes ``callable(*args, **kwargs) ``, then exits the
229+ Context. Returns *callable *'s return value, or propagates an exception if
230+ one occurred.
162231
163232 Example:
164233
@@ -206,10 +275,6 @@ Manual Context Management
206275 ham
207276 spam
208277
209- The method raises a :exc: `RuntimeError ` when called on the same
210- context object from more than one OS thread, or when called
211- recursively.
212-
213278 .. method :: copy()
214279
215280 Return a shallow copy of the context object.
0 commit comments