Yury Selivanov wrote:
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__.

If you tie the introduction of a new scope for context vars
to generators, as PEP 550 currently does, then this isn't a
problem.

But I'm trying to avoid doing that. The basic issue is that,
ever since yield-from, "generator" and "task" are not
synonymous.

When you use a generator to implement an iterator, you
probably want it to behave as a distinct task with its
own local context. But a generator used with yield-from
isn't a task of its own, it's just part of another task,
and there is nothing built into Python that lets you
tell the difference automatically.

So I'm now thinking that the introduction of a new local
context should also be explicit.

Suppose we have these primitives:

   push_local_context()
   pop_local_context()

Now introducing a temporary decimal context looks like:

   push_local_context()
   decimal.localcontextvar.new(decimal.getcontext().copy())
   decimal.localcontextvar.prec = 5
   do_some_calculations()
   pop_local_context()

Since calls (either normal or generator) no longer automatically
result in a new local context, we can easily factor this out into
a context manager:

   class LocalDecimalContext():

      def __enter__(self):
         push_local_context()
         ctx = decimal.getcontext().copy()
         decimal.localcontextvar.new(ctx)
         return ctx

      def __exit__(self):
         pop_local_context()

Usage:

   with LocalDecimalContext() as ctx:
      ctx.prec = 5
      do_some_calculations()

--
Greg




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

_______________________________________________
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

Reply via email to