Skip to content

Commit b55f4cf

Browse files
committed
pythongh-119333, pythongh-99633: Replace enter/exit events with "switched"
Users want to know when the current context switches to a different context object. Right now this happens when and only when a context is entered or exited, so the enter and exit events are synonymous with "switched". However, if the changes proposed for pythongh-99633 are implemented, the current context will also switch for reasons other than context enter or exit. Since users actually care about context switches and not enter or exit, replace the enter and exit events with a single switched event. The former exit event was emitted just before exiting the context. The new switched event is emitted after the context is exited to match the semantics users expect of an event with a past-tense name. If users need the ability to clean up before the switch takes effect, another event type can be added in the future. It is not added here because YAGNI. I skipped 0 in the enum as a matter of practice. Skipping 0 makes it easier to troubleshoot when code forgets to set zeroed memory, and it aligns with best practices for other tools (e.g., https://protobuf.dev/programming-guides/dos-donts/#unspecified-enum).
1 parent b9d7a04 commit b55f4cf

3 files changed

Lines changed: 11 additions & 29 deletions

File tree

‎Doc/c-api/contextvars.rst‎

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,9 @@ Context object management functions:
123123
124124
Enumeration of possible context object watcher events:
125125
126-
- ``Py_CONTEXT_EVENT_ENTER``: A context has been entered, causing the
127-
:term:`current context` to switch to it. The object passed to the watch
128-
callback is the now-current :class:`contextvars.Context` object. Each
129-
enter event will eventually have a corresponding exit event for the same
130-
context object after any subsequently entered contexts have themselves been
131-
exited.
132-
- ``Py_CONTEXT_EVENT_EXIT``: A context is about to be exited, which will
133-
cause the :term:`current context` to switch back to what it was before the
134-
context was entered. The object passed to the watch callback is the
135-
still-current :class:`contextvars.Context` object.
126+
- ``Py_CONTEXT_EVENT_CURRENT_SWITCHED``: The :term:`current context` has
127+
switched to a different context. The object passed to the watch callback
128+
is the now-current :class:`contextvars.Context` object.
136129
137130
.. versionadded:: 3.14
138131

‎Include/cpython/context.h‎

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,11 @@ PyAPI_FUNC(int) PyContext_Exit(PyObject *);
2929

3030
typedef enum {
3131
/*
32-
* A context has been entered, causing the "current context" to switch to
33-
* it. The object passed to the watch callback is the now-current
34-
* contextvars.Context object. Each enter event will eventually have a
35-
* corresponding exit event for the same context object after any
36-
* subsequently entered contexts have themselves been exited.
32+
* The current context has switched to a different context. The object
33+
* passed to the watch callback is the now-current contextvars.Context
34+
* object.
3735
*/
38-
Py_CONTEXT_EVENT_ENTER,
39-
/*
40-
* A context is about to be exited, which will cause the "current context"
41-
* to switch back to what it was before the context was entered. The
42-
* object passed to the watch callback is the still-current
43-
* contextvars.Context object.
44-
*/
45-
Py_CONTEXT_EVENT_EXIT,
36+
Py_CONTEXT_EVENT_CURRENT_SWITCHED = 1,
4637
} PyContextEvent;
4738

4839
/*

‎Python/context.c‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,8 @@ PyContext_CopyCurrent(void)
102102
static const char *
103103
context_event_name(PyContextEvent event) {
104104
switch (event) {
105-
case Py_CONTEXT_EVENT_ENTER:
106-
return "Py_CONTEXT_EVENT_ENTER";
107-
case Py_CONTEXT_EVENT_EXIT:
108-
return "Py_CONTEXT_EVENT_EXIT";
105+
case Py_CONTEXT_EVENT_CURRENT_SWITCHED:
106+
return "Py_CONTEXT_EVENT_CURRENT_SWITCHED";
109107
default:
110108
return "?";
111109
}
@@ -196,7 +194,7 @@ _PyContext_Enter(PyThreadState *ts, PyObject *octx)
196194
ts->context = Py_NewRef(ctx);
197195
ts->context_ver++;
198196

199-
notify_context_watchers(ts, Py_CONTEXT_EVENT_ENTER, ctx);
197+
notify_context_watchers(ts, Py_CONTEXT_EVENT_CURRENT_SWITCHED, ts->context);
200198
return 0;
201199
}
202200

@@ -230,13 +228,13 @@ _PyContext_Exit(PyThreadState *ts, PyObject *octx)
230228
return -1;
231229
}
232230

233-
notify_context_watchers(ts, Py_CONTEXT_EVENT_EXIT, ctx);
234231
Py_SETREF(ts->context, (PyObject *)ctx->ctx_prev);
235232
ts->context_ver++;
236233

237234
ctx->ctx_prev = NULL;
238235
ctx->ctx_entered = 0;
239236

237+
notify_context_watchers(ts, Py_CONTEXT_EVENT_CURRENT_SWITCHED, ts->context);
240238
return 0;
241239
}
242240

0 commit comments

Comments
 (0)