<div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace"><span style="font-family:arial,sans-serif">I'll quickly add a few things below just in case there's anyone that cares.</span></div><div class="gmail_default" style="font-family:monospace,monospace"><span style="font-family:arial,sans-serif"><br></span></div><div class="gmail_default" style="font-family:monospace,monospace"><span style="font-family:arial,sans-serif">On Wed, Jan 10, 2018 at 2:06 AM, Koos Zevenhoven </span><span dir="ltr" style="font-family:arial,sans-serif"><<a href="mailto:k7hoven@gmail.com" target="_blank">k7hoven@gmail.com</a>></span><span style="font-family:arial,sans-serif"> wrote:</span><br></div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">The idea was to always explicitly define the scope of contextvar values. A context manager / with statement determined the scope of .set(..) operations inside the with statement:</font></div><div><br></div><div><font face="monospace, monospace"># Version A:</font></div><div><font face="monospace, monospace">cvar.set(1)</font></div><div><font face="monospace, monospace">with context_scope():</font></div><div><font face="monospace, monospace">    cvar.set(2)</font></div><div><font face="monospace, monospace">    </font></div><div><font face="monospace, monospace">    assert cvar.get() == 2</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">assert cvar.get() == 1</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">Then I added the ability to define scopes for different variables separately:</font></div><div><br></div><div><font face="monospace, monospace"># Version B</font></div><div><font face="monospace, monospace">cvar1.set(1)</font></div><div><font face="monospace, monospace">cvar2.set(2)</font></div><div><font face="monospace, monospace">with context_scope(cvar1):</font></div><div><font face="monospace, monospace">    cvar1.set(11)</font></div><div><font face="monospace, monospace">    cvar2.set(22)<br></font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">assert cvar1.get() == 1</font></div><div><font face="monospace, monospace">assert cvar2.get() == 22</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">However, in practice, most libraries would wrap __enter__, set and __exit__ into another context manager. So maybe one might want to allow something like </font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><div><font face="monospace, monospace"># Version C:</font></div><div><span style="font-family:monospace,monospace">assert cvar.get() == something</span><br></div><div><font face="monospace, monospace">with context_scope(cvar, 2):</font></div><div><span style="font-family:monospace,monospace">    assert cvar.get() == 2</span><br></div><div><font face="monospace, monospace"><br></font></div><div><span style="font-family:monospace,monospace">assert cvar.get() == something</span><br></div></div><div><font face="arial, helvetica, sans-serif"><br></font></div></div></blockquote><div><br></div><div class="gmail_default" style="font-family:monospace,monospace">Note here, that the point is to get a natural way to "undo" changes made to variables when exiting the scope. Undoing everything that is done within the defined scope is a very natural way to do it. Undoing individual .set(..) operations is more problematic.</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">Features B+C could be essentially implemented as described in PEP 555, except with context_scope(cvar) being essentially the same as pushing and popping an empty Assignment object onto the reverse-linked stack. By empty, I mean a "key-value pair with a missing value". Then any set operations would replace the topmost assignment object for that variable with a new key-value pair (or push a new Assignment if there isn't one).</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">​However, to also get feature A, the stack may have to contain full mappings instead of assignemnt objects with just one key-value pair.</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">I hope that clarifies some parts. Otherwise, in terms of semantics, the same things apply as for PEP 555 when it comes to generator function calls and next(..) etc., so we'd need to make sure it works well enough for all use cases. For instance, I'm not quite sure if I have a good enough understanding of the timeout example that Nathaniel wrote in the PEP 550 discussion to tell what would be required in terms of semantics, but I suppose it should be fine. </div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">-- Koos</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><font face="arial, helvetica, sans-serif"></font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif">But this then led to combining "__enter__" and ".set(..)" into Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this:</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><font face="arial, helvetica, sans-serif"># PEP 555 draft version:</font></div><div><font face="monospace, monospace">assert cvar.value == something</font></div><div><span style="font-family:monospace,monospace">with cvar.assign(1):</span><br></div><div><font face="monospace, monospace">    assert cvar.value == 1</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">assert cvar.value == something</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div><br></div><div>Anyway, given the schedule, I'm not really sure about the best thing to do here. In principle, something like in versions A, B and C above could be done (I hope the proposal was roughly self-explanatory based on earlier discussions). However, at this point, I'd probably need a lot of help to make that happen for 3.7.<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><div><div><br></div></div><div><font face="arial, helvetica, sans-serif">-- Koos</font></div><div><br></div>
</font></span></div>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature">+ Koos Zevenhoven + <a href="http://twitter.com/k7hoven" target="_blank">http://twitter.com/k7hoven</a> +</div>
</div></div>