[Python-Dev] PEP 550 v4
Yury Selivanov
yselivanov.ml at gmail.com
Wed Aug 30 09:55:59 EDT 2017
On Wed, Aug 30, 2017 at 8:55 AM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
> Yury Selivanov wrote:
>
>> BTW we already have mechanisms to always propagate context to the
>> caller -- just use threading.local() or a global variable.
>
>
> But then you don't have a way to *not* propagate the
> context change when you don't want to.
>
> Here's my suggestion: Make an explicit distinction between
> creating a new binding for a context var and updating an
> existing one.
>
> So instead of two API calls there would be three:
>
> contextvar.new(value) # Creates a new binding only
> # visible to this frame and
> # its callees
>
> contextvar.set(value) # Updates existing binding in
> # context inherited from caller
>
> contextvar.get() # Retrieves the current binding
>
> If we assume an extension to the decimal module so
> that decimal.localcontext is a context var, we can
> now do this:
>
> async def foo():
> # Establish a new context for this task
> decimal.localcontext.new(decimal.Context())
> # Delegate changing the context
> await bar()
> # Do some calculations
> yield 17 * math.pi + 42
>
> async def bar():
> # Change context for caller
> decimal.localcontext.prec = 5
Interesting.
Question: how to write a context manager with contextvar.new?
var = new_context_var()
class CM:
def __enter__(self):
var.new(42)
with CM():
print(var.get() or 'None')
My understanding that the above code will print "None", because
"var.new()" makes 42 visible only to callees of __enter__.
But if I use "set()" in "CM.__enter__", presumably, it will traverse
the stack of LCs to the very bottom and set "var=42" in in it. Right?
If so, how can fix the example in PEP 550 Rationale:
https://www.python.org/dev/peps/pep-0550/#rationale where we zip() the
"fractions()" generator?
With current PEP 550 semantics that's trivial:
https://www.python.org/dev/peps/pep-0550/#generators
Yury
More information about the Python-Dev
mailing list