I am +1 on everything Yury says here. On Mon, Jan 8, 2018 at 11:34 AM, Yury Selivanov <yselivanov...@gmail.com> wrote:
> Hi, > > Thanks to everybody participating in the PEP 567 discussion! I want > to summarize a few topics to make sure that we are all on the same > page (and maybe provoke more discussion). > > > 1. Proposal: ContextVar has default set to None. > > From the typing point of view that would mean that if a context > variable is declared without an explicit default, its type would be > Optional. E.g. say we have a hypothetical web framework that allows > to access the current request object through a context variable: > > request_var: ContextVar[Optional[Request]] = \ > ContextVar('current_request') > > When we need to get the current request object, we would write: > > request: Optional[Request] = request_var.get() > > And we'd also need to explicitly handle when 'request' is set to None. > Of course we could create request_var with its default set to some > "InvalidRequest" object, but that would complicate things. It would > be easier to just state that the framework always sets the current > request and it's a bug if it's not set. > > Therefore, in my opinion, it's better to keep the current behaviour: > if a context variable was created without a default value, > ContextVar.get() can raise a LookupError. > > > 2. Context.__contains__, Context.__getitem__ and ContexVar.default > > So if we keep the current PEP 567 behaviour w.r.t. defaults, > ContextVar.get() might return a different value from Context.get(): > > v = ContextVar('v', default=42) > ctx = contextvars.copy_context() > > ctx.get(v) # returns None > v.get() # returns 42 > v in ctx # returns False > > I think this discrepancy is OK. Context is a mapping-like object and > it reflects the contents of the underlying _ContextData mapping > object. > > ContextVar.default is meant to be used only by ContextVar.get(). > Context objects should not use it. > > Maybe we can rename ContextVar.get() to ContextVar.lookup()? This > would help to avoid potential confusion between Context.get() and > ContextVar.get(). > > > 3. Proposal: Context.get() and __getitem__() should always return up > to date values. > > The issue with the current PEP 567 design is that PyThreadState points > to a _ContextData object, and not to the current Context. The > following code illustrates how this manifests in Python code: > > v = ContextVar('v') > > def foo(): > v.set(42) > print(v.get(), ctx.get(v, 'missing')) > > ctx = Context() > ctx.run(foo) > > The above code will print "42 missing", because 'ctx' points to an > outdated _ContextData. > > This is easily fixable if we make PyThreadState to point to the > current Context object (instead of it pointing to a _ContextData). > This change will also make "contextvars.copy_context()" easier to > understand--it will actually return a copy of the current context that > the thread state points to. > > Adding a private Context._in_use attribute would allow us to make sure > that Context.run() cannot be simultaneously called in two OS threads. > As Nathaniel points out, this will also simplify cache implementation > in ContextVar.get(). So let's do this. > > > 4. Add Context.copy(). > > I was actually going to suggest this addition myself. With the > current PEP 567 design, Context.copy() can be implemented with > "ctx.run(contextvars.copy_context)", but this is very cumbersome. > > An example of when a copy() method could be useful is capturing the > current context and executing a few functions with it using > ThreadPoolExecutor.map(). Copying the Context object will ensure that > every mapped function executes in its own context copy (i.e. > isolated). So I'm +1 for this one. > > > 5. PEP language. > > I agree that PEP is vague about some details and is incorrect in some > places (like calling Context objects immutable, which is not really > true, because .run() can modify them). I'll fix the language in v3 > once I'm back home. > > > Yury > _______________________________________________ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: https://mail.python.org/mailman/options/python-dev/ > guido%40python.org > -- --Guido van Rossum (python.org/~guido)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com