On Sun, Oct 15, 2017 at 9:44 AM, Koos Zevenhoven <k7hoven@gmail.com> wrote:
So, see below for some more discussion between (it would be useful if some people could reply to this email and say if and why they agree or disagree with something below -- also non-experts that roughly understand what I'm talking about):

Yes, I understand what you are roughly talking about.

Also, yes, generators are co-routines [though when starting to work with generators, people don't fully realize this].

But then how to address "my" original problem where the context would propagate through awaits, and next/send? From what others have written, it seems there are also other situations where that is desired. There are several ways to solve the problem as an extension to PEP 555, but below is one:

 
​We need both versions: the one that propagates first_context() into the coroutine, and the one that propagates second_context() into it. Or, using my metaphor from the other thread, we need "both the forest and the trees". ​

​A solution to this would be to have two types of context arguments:

1. (calling) context arguments​ 

and 

2. execution context arguments



So yes, I'm actually serious about this possibility. Now it would be up to library and framework authors to pick the right variant of the two. And this is definitely something that could be documented very clearly.​


This is an interesting idea.  I would add you also need:

3.  Shared context, the generator shares the context with it's caller which means:
  • If the caller changes the context, the generator, see the changed context next time it's __next__ function is called
  • If the generator changes the context, the caller sees the changed context.
  • [This clearly make changing the context using 'with' totally unusable in both the caller & the generator -- unless we add even odder semantics, that the generator restores the original context when it exists???]
  • (As per previous email by me, I claim this is the most natural way beginners are going to think it works; and needs to be supported; also in real code this is not often useful]
  • I'm not sure if this would even work with async or not -- *IF* not, I would still have a syntax for the user to attempt this -- and throw a Syntax Error when they do, with a good explanation of why this combination doesn't work for async.  I believe good explanations are a great way for people to learn which features can't be combined together & why.

If something was not clear, but seems relevant to what I'm trying to discuss here, please ask :)


I looked for you quote "we need both the forest & the trees", but didn't find it here.  I quite strongly agree we need both; in fact need also the third case I highlighted above.

As for what Guido wrote, that we might be trying to solve too many problems -- probably.  However, these are real issues with context's, not edge cases. 

Thus Guido writing we don't want to allow yield within a 'with' clause (as it leaks context) .. I would argue two things:
  • There are use cases where we *DO* want this -- rare -- true -- but they exist (i.e.: my #3 above)

  • IF, for simplicity, sake, it is decided not to handle this case now; then make it a syntax error in the language; i.e.:

       def f():
          with context() as x:
             yield 1

    Syntax error: 'yield' may not be used inside a 'with' clause.

This would really help new users not to make a mistake that takes hours to debug; & help correct their [initial mistaken] thinking on how contexts & generators interact.