Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace context enter and exit events with single "context switched" event #124872

Open
rhansen opened this issue Oct 1, 2024 · 18 comments
Open
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement

Comments

@rhansen
Copy link
Contributor

rhansen commented Oct 1, 2024

Feature or enhancement

Proposal:

(split off of #99633 (comment) to keep related pull requests and discussion better organized)

Starting in v3.14, C code can subscribe to "context enter" and "context exit" events:

typedef enum {
Py_CONTEXT_EVENT_ENTER,
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.
*
* if the callback returns with an exception set, it must return -1. Otherwise
* it should return 0
*/
typedef int (*PyContext_WatchCallback)(PyContextEvent, PyContext *);
/*
* Register a per-interpreter callback that will be invoked for context object
* enter/exit events.
*
* Returns a handle that may be passed to PyContext_ClearWatcher on success,
* or -1 and sets and error if no more handles are available.
*/
PyAPI_FUNC(int) PyContext_AddWatcher(PyContext_WatchCallback callback);
/*
* Clear the watcher associated with the watcher_id handle.
*
* Returns 0 on success or -1 if no watcher exists for the provided id.
*/
PyAPI_FUNC(int) PyContext_ClearWatcher(int watcher_id);

See gh-119333 for some background.

I would like to replace the just-added "context enter" and "context exit" events with a single "context switched" event:

diff --git a/Include/cpython/context.h b/Include/cpython/context.h
index ec72966e82c..f9638b0abe5 100644
--- a/Include/cpython/context.h
+++ b/Include/cpython/context.h
@@ -28,8 +28,12 @@ PyAPI_FUNC(int) PyContext_Enter(PyObject *);
 PyAPI_FUNC(int) PyContext_Exit(PyObject *);
 
 typedef enum {
-   Py_CONTEXT_EVENT_ENTER,
-   Py_CONTEXT_EVENT_EXIT,
+    /*
+     * The current context has switched to a different context.  The object
+     * passed to the watch callback is the now-current contextvars.Context
+     * object.
+     */
+    Py_CONTEXT_SWITCHED = 1,
 } PyContextEvent;
 
 /*
diff --git a/Python/context.c b/Python/context.c
index ddb03555f9e..6c9f68583c2 100644
--- a/Python/context.c
+++ b/Python/context.c
@@ -192,7 +192,7 @@ _PyContext_Enter(PyThreadState *ts, PyObject *octx)
     ts->context = Py_NewRef(ctx);
     ts->context_ver++;
 
-    notify_context_watchers(Py_CONTEXT_EVENT_ENTER, ctx, ts);
+    notify_context_watchers(Py_CONTEXT_SWITCHED, ctx, ts);
     return 0;
 }
 
@@ -226,13 +226,13 @@ _PyContext_Exit(PyThreadState *ts, PyObject *octx)
         return -1;
     }
 
-    notify_context_watchers(Py_CONTEXT_EVENT_EXIT, ctx, ts);
     Py_SETREF(ts->context, (PyObject *)ctx->ctx_prev);
     ts->context_ver++;
 
     ctx->ctx_prev = NULL;
     ctx->ctx_entered = 0;
 
+    notify_context_watchers(Py_CONTEXT_SWITCHED, (PyContext *)ts->context, ts);
     return 0;
 }
 

Rationale: 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 gh-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, replacing the enter and exit events with a single switched event would make the new feature compatible with gh-99633.

The current "context exit" event is emitted just before exiting the context. The new "context switched" event would be 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 "context is about to switch" event can be added in the future. I am not proposing to add such an event for this issue because no users have requested it yet (YAGNI).

I would love to get this resolved before v3.14 is released so that we don't have to worry about breaking backwards compatibility.

Has this already been discussed elsewhere?

I have already discussed this feature proposal on another bug report.

Links to previous discussion of this feature:

#99633 (comment)

Linked PRs

@rhansen rhansen added the type-feature A feature request or enhancement label Oct 1, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Oct 1, 2024
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).
@ZeroIntensity
Copy link
Member

Generally, it's a bad idea to create several different PRs for the same issue -- you can put all the needed changes in the same PR.

rhansen added a commit to rhansen/cpython that referenced this issue Oct 2, 2024
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).
@rhansen
Copy link
Contributor Author

rhansen commented Oct 2, 2024

Apologies—I was under the impression that this project squashes pull requests when merging, which I don't want (the commits are intended to be separate). I can combine them into a single PR if that would be preferred.

@ZeroIntensity
Copy link
Member

We do squash, but why do you want the commits to be separate? It's harder to review and backport across multiple PRs

@rhansen
Copy link
Contributor Author

rhansen commented Oct 2, 2024

I'm following the Python Developer's Guide:

  • Do not fix more than one issue in the same commit (except, of course, if one code change fixes all of them).
  • Do not do cosmetic changes to unrelated code in the same commit as some feature/bugfix.

Each of these PRs is focused on only one thing, and they are independent from each other (but all support the overall goal of this issue).

In general, it's bad practice to have large monolithic commits that do multiple separable things. Small, focused, and independent commits have several advantages:

  • They are better for locating the root cause of a bug by bisecting.
  • They are easier to cherry-pick and rebase (less likely to have merge conflicts).
  • They are easier to revert if a bug is found.
  • Most importantly, they are easier to understand both by current reviewers and by future code archaeologists trying to understand past design decisions.

I can put all of the commits in a single pull request, but if they are squashed then much will be lost.

rhansen added a commit to rhansen/cpython that referenced this issue Oct 2, 2024
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).
@ZeroIntensity
Copy link
Member

ZeroIntensity commented Oct 2, 2024

Each of these PRs is focused on only one thing, and they are independent from each other (but all support the overall goal of this issue).

In that case, it's better to make a new issue for each PR (I don't think it's worth doing so at this point, but this is just for future reference). If they really are all "independent", then having all the PRs under one issue makes this more difficult for us. If, for example, one PR gets merged while another gets shot down, what do we do about this issue? Does it stay closed or open?

  • Most importantly, they are easier to understand both by current reviewers and by future code archaeologists trying to understand past design decisions.

Eh, looking through a tree of "related yet independent" PRs is arguably more difficult for people trying to understand design decisions. With one PR, all the reviews are in one place. For example, #124774 looks like a cosmetic change -- it would honestly fit better in a larger PR, where there's lots of other refactoring going on (and also easier to review without being brushed off as cosmetic).

I can put all of the commits in a single pull request, but if they are squashed then much will be lost.

GitHub saves the commits for us :)

In terms of bisecting, we can always checkout the branch that got merged and bisect to individual commits on it. But in my experience, we haven't ever needed to do that. Once we've found a bad commit, it's typically easy to figure out what went wrong without doing any extra micro-bisections.

rhansen added a commit to rhansen/cpython that referenced this issue Oct 2, 2024
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).
@rhansen
Copy link
Contributor Author

rhansen commented Oct 2, 2024

Each of these PRs is focused on only one thing, and they are independent from each other (but all support the overall goal of this issue).

In that case, it's better to make a new issue for each PR (I don't think it's worth doing so at this point, but this is just for future reference).

Creating a separate issue per PR seems like a heavyweight process to me. Why have two places to discuss the same thing? Though I understand if it makes it easier for the project to track done/pending status.

Also, I think it's easier to understand relationships between changes if there is one issue with N associated pull requests vs. N separate issues with one corresponding pull request each.

If they really are all "independent", then having all the PRs under one issue makes this more difficult for us. If, for example, one PR gets merged while another gets shot down, what do we do about this issue? Does it stay closed or open?

How about: "If there are any open PRs associated with an issue, then the issue is not yet resolved."

  • Most importantly, they are easier to understand both by current reviewers and by future code archaeologists trying to understand past design decisions.

Eh, looking through a tree of "related yet independent" PRs is arguably more difficult for people trying to understand design decisions. With one PR, all the reviews are in one place. For example, #124774 looks like a cosmetic change -- it would honestly fit better in a larger PR, where there's lots of other refactoring going on (and also easier to review without being brushed off as cosmetic).

I think the ideal solution would be to require contributors to indicate whether their PR is intended to be squashed vs. rebased-then-merged (aka semi-linear history):

  • Squash PRs would be treated as they are now.
  • Rebase-then-merge PRs would be rebased onto latest main then merged with a merge commit (git merge --no-ff). Contributors would be expected to frequently rebase and force-push their PR branch to address review comments, resolve conflicts with main, etc.

Rebase-then-merge PRs would be easier to review/manage/understand vs. N separate PRs, but would still have the advantages of N small and focused commits. The N commits would be grouped together in the Git history, linked to main with a merge commit that references the PR. This makes it easy to see that they are related and all part of a particular pull request. Also, Git's --first-parent option can be used to bisect/examine the history at PR granularity.

Unfortunately, the review experience is still not great when force pushes are involved. Also, GitHub has poor/no support for semi-linear history (GitLab is superior in this regard). It can still be done manually, but this is error-prone and tedious. Maybe bots can help. Maybe someone has already written one.

I can put all of the commits in a single pull request, but if they are squashed then much will be lost.

GitHub saves the commits for us :)

git blame doesn't walk GitHub PR commits.

In terms of bisecting, we can always checkout the branch that got merged and bisect to individual commits on it.

This doesn't work for PRs written with the expectation that the commits will be squashed. Such PRs often have intermediate commits that are works-in-progress (they don't compile, don't pass tests, etc.).

But in my experience, we haven't ever needed to do that. Once we've found a bad commit, it's typically easy to figure out what went wrong without doing any extra micro-bisections.

True.

@ZeroIntensity
Copy link
Member

All in all, this isn't common practice for CPython. Let's try to stick with tradition :)

@rhansen
Copy link
Contributor Author

rhansen commented Oct 2, 2024

On a related note, it would be nice if this tradition was documented in the devguide. :)

@ZeroIntensity
Copy link
Member

ZeroIntensity commented Oct 2, 2024

It is, sort of. There's supposed to be an implied 1:1 correspondence between issues and PRs (with the exception of backports).

rhansen added a commit to rhansen/cpython that referenced this issue Oct 7, 2024
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).
1st1 pushed a commit that referenced this issue Oct 9, 2024
* 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.
  * Expand the documentation for the `Py_CONTEXT_EVENT_ENTER` and
    `Py_CONTEXT_EVENT_EXIT` events to clarify and to prepare for
    planned changes.
rhansen added a commit to rhansen/cpython that referenced this issue Oct 10, 2024
  * 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 9940093)
rhansen added a commit to rhansen/cpython that referenced this issue Oct 10, 2024
I opened issue pythongh-124872 after creating PR pythongh-124773 but forgot to
rename the blurb file to match the new issue number.  (The cherry-pick
to 3.13 in pythongh-125233 already uses this new filename.)
@picnixz
Copy link
Member

picnixz commented Oct 11, 2024

On the essence of this issue: while I agree that most of the time you only want to know whether the context switched or not, is there actually a way to keep the enter/exit events?

When you enter or exit, you switch. But what if you really want to, say, track down the enter/exit events and not just any kind of switch? (like, you want to count that the number of times you exited is the same as the number of times you entered). I don't know whether this is me who's trying to find issues where there are none, but I usually like events with granularity, even though I don't know if I would use them for now.

@picnixz picnixz added extension-modules C modules in the Modules dir and removed extension-modules C modules in the Modules dir labels Oct 11, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Oct 12, 2024
…back

I believe that the value of a simpler API (and defense against poorly
written callbacks) outweighs the cost of backing up and restoring the
thread's exception state.
rhansen added a commit to rhansen/cpython that referenced this issue Oct 12, 2024
The exception is ignored so change the return type from `int` to
`void` to discourage callbacks from raising an exception in the first
place.
rhansen added a commit to rhansen/cpython that referenced this issue Oct 12, 2024
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).
rhansen added a commit to rhansen/cpython that referenced this issue Oct 12, 2024
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).
@rhansen
Copy link
Contributor Author

rhansen commented Oct 12, 2024

Per the PR description, the related PRs: #124737, #124741, and #124774 need to be merged first.

All of the related PRs have been merged (thank you!) except #124741. I rebased #124776 (the core of this issue) onto latest main, excluding #124741 which appears to be a bit more controversial so I didn't want it to block #124776.

#124776 is now marked as ready for review, and this issue can be closed once that PR is merged even if #124741 is still open.

(Personally, I would have rathered all the needed changes in one PR, but the damage is done at this point.)

Me too. Normally I would put all commits in a single PR, but this project squashes all PRs. I've been burned in the past by single commits doing too many things—for example, bugs introduced by failing to correctly revert or cherry-pick a portion of a monolithic commit. If it was possible to choose a semi-linear merge instead of a squash when opening a PR I would have opened a single PR with multiple commits.

rhansen added a commit to rhansen/cpython that referenced this issue Oct 14, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Oct 14, 2024
The callback cannot prevent the event from occurring by raising an
exception.  Nor should it be able to; any failure to switch contexts
would be difficult if not impossible to handle correctly.  The API
should reflect that the callback is purely informational, and that the
context switch will happen even if the callback doesn't want it to.
1st1 pushed a commit that referenced this issue Oct 14, 2024
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 gh-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).
Eclips4 added a commit to Eclips4/cpython that referenced this issue Oct 15, 2024
Eclips4 added a commit to Eclips4/cpython that referenced this issue Oct 15, 2024
Eclips4 pushed a commit to Eclips4/cpython that referenced this issue Oct 16, 2024
…4776)

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).
ambv pushed a commit that referenced this issue Oct 16, 2024
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 gh-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).

Co-authored-by: Richard Hansen <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
rhansen added a commit to rhansen/cpython that referenced this issue Oct 16, 2024
Starting with commit 843d28f
(temporarily reverted in d3c82b9 and
restored in commit bee112a), it is
now technically possible to access a thread's initial context created
by `context_get`.  Mark that context as entered so that developers
cannot push that context onto the thread's stack a second time, which
would cause a cycle.

(Even if the `CONTEXT_SWITCHED` event is removed, this is good
defensive practice, and the consistent treatment of all contexts on
the stack makes it easier to understand the code.)
rhansen added a commit to rhansen/cpython that referenced this issue Oct 17, 2024
Starting with commit 843d28f
(temporarily reverted in d3c82b9 and
restored in commit bee112a), it is
now technically possible to access a thread's default context created
by `context_get`.  Mark that context as entered so that users cannot
push that context onto the thread's stack a second time, which would
cause a cycle.

Also exit that context when the thread exits, for symmetry and in case
the user wants to re-enter it for some reason.

(Even if the `CONTEXT_SWITCHED` event is removed, entering the default
context is good defensive practice, and the consistent treatment of
all contexts on the stack makes it easier to understand the code.)
rhansen added a commit to rhansen/cpython that referenced this issue Oct 17, 2024
Starting with commit 843d28f
(temporarily reverted in d3c82b9 and
restored in commit bee112a), it is
now technically possible to access a thread's default context created
by `context_get`.  Mark that context as entered so that users cannot
push that context onto the thread's stack a second time, which would
cause a cycle.

This change also causes a `CONTEXT_SWITCHED` event to be emitted when
the default context is created, which might be important in some use
cases.

Also exit the default context when the thread exits, for symmetry and
in case the user wants to re-enter it for some reason.

(Even if the `CONTEXT_SWITCHED` event is removed, entering the default
context is good defensive practice, and the consistent treatment of
all contexts on the stack makes it easier to understand the code.)
rhansen added a commit to rhansen/cpython that referenced this issue Oct 17, 2024
Starting with commit 843d28f
(temporarily reverted in d3c82b9 and
restored in commit bee112a), it is
now technically possible to access a thread's default context created
by `context_get`.  Mark that context as entered so that users cannot
push that context onto the thread's stack a second time, which would
cause a cycle.

This change also causes a `CONTEXT_SWITCHED` event to be emitted when
the default context is created, which might be important in some use
cases.

Also exit the default context when the thread exits, for symmetry and
in case the user wants to re-enter it for some reason.

(Even if the `CONTEXT_SWITCHED` event is removed, entering the default
context is good defensive practice, and the consistent treatment of
all contexts on the stack makes it easier to understand the code.)
rhansen added a commit to rhansen/cpython that referenced this issue Oct 17, 2024
Starting with commit 843d28f
(temporarily reverted in d3c82b9 and
restored in commit bee112a), it is
now technically possible to access a thread's default context created
by `context_get`.  Mark that context as entered so that users cannot
push that context onto the thread's stack a second time, which would
cause a cycle.

This change also causes a `CONTEXT_SWITCHED` event to be emitted when
the default context is created, which might be important in some use
cases.

Also exit the default context when the thread exits, for symmetry and
in case the user wants to re-enter it for some reason.

(Even if the `CONTEXT_SWITCHED` event is removed, entering the default
context is good defensive practice, and the consistent treatment of
all contexts on the stack makes it easier to understand the code.)
rhansen added a commit to rhansen/cpython that referenced this issue Oct 17, 2024
Starting with commit 843d28f
(temporarily reverted in d3c82b9 and
restored in commit bee112a), it is
now technically possible to access a thread's default context created
by `context_get`.  Mark that context as entered so that users cannot
push that context onto the thread's stack a second time, which would
cause a cycle.

This change also causes a `CONTEXT_SWITCHED` event to be emitted when
the default context is created, which might be important in some use
cases.

Also exit the default context when the thread exits, for symmetry and
in case the user wants to re-enter it for some reason.

(Even if the `CONTEXT_SWITCHED` event is removed, entering the default
context is good defensive practice, and the consistent treatment of
all contexts on the stack makes it easier to understand the code.)
willingc added a commit to rhansen/cpython that referenced this issue Oct 30, 2024
willingc added a commit that referenced this issue Oct 30, 2024
[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 9940093)

Co-authored-by: Carol Willing <[email protected]>
rhansen added a commit to rhansen/cpython that referenced this issue Nov 7, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Nov 7, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Nov 7, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Nov 10, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Nov 23, 2024
rhansen added a commit to rhansen/cpython that referenced this issue Nov 23, 2024
ebonnal pushed a commit to ebonnal/cpython that referenced this issue Jan 12, 2025
…5532)

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).

Co-authored-by: Richard Hansen <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

6 participants