-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
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
Pass opaque state to PyContext_AddWatcher callback #127124
Comments
This enables users to associate state with the callback without relying on globals. Also: * Refactor the tests for improved readability and extensibility, and to cover the new opaque pointer. * Drop the pointer from the `PyContext_WatchCallback` typedef. This de-obfuscates the fact that pointers are involved, and makes it possible to forward-declare functions to improve readability: static PyContext_WatchCallback my_callback; int my_callback(void *arg, PyContextEvent event, PyObject *obj) { ... }
These aren't unsolvable problems, but I think the approach would be much easier if we just allowed passing a Python object, which has answered all of these questions. If the user really wants some C data, they can use a capsule. |
I can do Spitballing: Instead of a function pointer + object, WDYT about taking a callable object? That would be more awkward to use from C, unless there's a utility function I'm unaware of that wraps a C function pointer inside a callable. |
That might be better, it would unlock some more use cases. You can use |
This enables users to associate state with the callback without relying on globals. Also: * Refactor the tests for improved readability and extensibility, and to cover the new state object. * Drop the pointer from the `PyContext_WatchCallback` typedef. This de-obfuscates the fact that pointers are involved, and makes it possible to forward-declare functions to improve readability: static PyContext_WatchCallback my_callback; int my_callback(PyObject *cbarg, PyContextEvent event, PyObject *obj) { ... }
This enables users to associate state with the callback without relying on globals. Also: * Refactor the tests for improved readability and extensibility, and to cover the new state object. * Drop the pointer from the `PyContext_WatchCallback` typedef. This de-obfuscates the fact that pointers are involved, and makes it possible to forward-declare functions to improve readability: static PyContext_WatchCallback my_callback; int my_callback(PyObject *cbarg, PyContextEvent event, PyObject *obj) { ... }
This enables developers to associate state with the callback without relying on globals. Also, refactor the tests for improved readability and extensibility, and to cover the new state object.
Feature or enhancement
Proposal:
I would like to change the Context watcher C API (new to v3.14, see #119333) to pass an opaque pointer to the callback. Specifically, change:
cpython/Include/cpython/context.h
Lines 39 to 55 in e8bb053
to:
The original idea was for the callback to get any required state from the current context, but:
ctx = contextvars.Context()
instead ofctx = contextvars.copy_context()
. Or it can docopy_context()
, but early during initialization and squirrel the context away for later use. The latter seems plausible for 3rd party libraries (where the user might not have much control).TestContextObjectWatchers
to add some more tests for a change I’m working on.I’m not sure how likely either is to come up in normal use, but I think it is worth changing the design before the 3.14 release cements it.
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
https://discuss.python.org/t/v3-14a1-design-limitations-of-pycontext-addwatcher/68177/4
cc @fried
Linked PRs
The text was updated successfully, but these errors were encountered: