Okay, I guess I should more fully explain.
contextvars have thread local documented behavior from day 1 here. That behavior was clear, though surprising to those who hadn’t read the docs or implementation. The free-threading behavior being different is surprising to those who wrote their code knowing the prior behavior.
I think everyone here agrees it wasn’t the right choice, but changing this behavior isn’t a fix, it’s a behavior change that we believe results in it being a more useful tool.
Those already using it knowing it was thread-local have working code that might be broken by changing this, Those whose code never hit cases where it being thread-local mattered have working code that should tolerate this being changed.
The problem is that in 3.14 we went from “This is the behavior” to “This is the default, and it might change under you with an interpreter setting”, so while library authors can shrug if they want and say “you set something that breaks the documented behavior”, that makes the setting a no-go as a real solution here. It also means that as of python 3.14, especially for libraries that want to support both the GIL-enabled and free-threading, libraries already need to behave correctly under both cases.
One of the parts I take some issue with is this is proposed as a temporary transition API.
If we’re able to acknowledge that both behaviors have valid uses, then this should probably just be a planned permanent API, not one that’s already being seen as something to deprecate in the future.
If we’re taking the stance that context-local should always include thread spawning, and that it not being this way a mistake that we don’t care that people unfortunately relied on, we don’t need this API, we can set a date for when users can expect this to switch, but until that point in time, libaries shouldn’t be relying on contextvars to handle this without some wrapping on their part.
It’s not clear to me which of these stances on behavior everyone here thinks is the case, but this API being added with a plan to deprecate it seems to be getting the worst of both of those stances.
I’m not going to adopt an already planned-to-be-deprecated API if I already have to work around this before the version it’s available.
If both behaviors are valid then this shouldn’t be deprecated. This outcome is fine with me, the API becomes adoptable when 3.15/3.16 is my minimum, and it’s nicer than the wrapping currently required.
If it’s intentional to on the long-term view invalidate the previous documented behavior even with code that relies on it, that makes the API more of a nuisance than a help, because it’s going to result in multiple stages of code churn for a moving target in python’s behavior. Even if the wrapping without the API is more annoying, it’s also going to be required to stick around after the date of the deprecation if libraries want the previous behavior (the one they in theory were designed for)