[Python-ideas] PEP draft: context variables
Nick Coghlan
ncoghlan at gmail.com
Mon Oct 9 02:46:13 EDT 2017
On 8 October 2017 at 08:40, Koos Zevenhoven <k7hoven at gmail.com> wrote:
> On Sun, Oct 8, 2017 at 12:16 AM, Nathaniel Smith <njs at pobox.com> wrote:
>
>> On Oct 7, 2017 12:20, "Koos Zevenhoven" <k7hoven at gmail.com> wrote:
>>
>>
>> Unfortunately, we actually need a third kind of generator semantics,
>> something like this:
>>
>> @contextvars.caller_context
>> def genfunc():
>> assert cvar.value is the_value
>> yield
>> assert cvar.value is the_value
>>
>> with cvar.assign(the_value):
>> gen = genfunc()
>>
>> next(gen)
>>
>> with cvar.assign(1234567890):
>> try:
>> next(gen)
>> except StopIteration:
>> pass
>>
>> Nick, Yury and I (and Nathaniel, Guido, Jim, ...?) somehow just narrowly
>> missed the reasons for this in discussions related to PEP 550. Perhaps
>> because we had mostly been looking at it from an async angle.
>>
>>
>> That's certainly a semantics that one can write down (and it's what the
>> very first version of PEP 550 did),
>>
>
> I do remember Yury mentioning that the first draft of PEP 550 captured
> something when the generator function was called. I think I started reading
> the discussions after that had already been removed, so I don't know
> exactly what it was. But I doubt that it was *exactly* the above, because
> PEP 550 uses set and get operations instead of "assignment contexts" like
> PEP 555 (this one) does.
>
We didn't forget it, we just don't think it's very useful. However, if you
really want those semantics under PEP 550, you can do something like this:
def use_creation_context(g):
@functools.wraps(g)
def make_generator_wrapper(*args, **kwds):
gi = g(*args, **kwds)
return _GeneratorWithCapturedEC(gi)
return make_generator_wrapper
class _GeneratorWithCapturedEC:
def __init__(self, gi):
self._gi = gi
self._ec = contextvars.get_execution_context()
def __next__(self):
return self.send(None)
def send(self, value):
return contextvars.run_with_execution_context(self.ec,
self._gi.send, value)
def throw(self, *exc_details):
return contextvars.run_with_execution_context(self.ec,
self._gi.throw, *exc_details)
def close(self):
return self.throw(GeneratorExit)
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20171009/55fe10dd/attachment.html>
More information about the Python-ideas
mailing list