Re: [Python-Dev] PEP 567 pre v3
On Wed, Jan 10, 2018 at 10:58 PM, Yury Selivanov wrote: > On Thu, Jan 11, 2018 at 10:35 AM, Chris Jerdonek > wrote: >> On Mon, Jan 8, 2018 at 11:02 PM, Nathaniel Smith wrote: >>> Right now, the set of valid states for a ContextVar are: it can hold >>> any Python object, or it can be undefined. However, the only way it >>> can be in the "undefined" state is in a new Context where it has never >>> had a value; once it leaves the undefined state, it can never return >>> to it. >> >> I know Yury responded to one aspect of this point later on in the >> thread. However, in terms of describing the possible states without >> reference to the internal Context mappings, IIUC, wouldn't it be more >> accurate to view a ContextVar as a stack of values rather than just >> the binary "holding an object or not"? This is to reflect the number >> of times set() has been called (and so the number of times reset() >> would need to be called to "empty" the ContextVar). > > > But why do you want to think of ContextVar as a stack of values? Or > as something that is holding even one value? I was primarily responding to Nathaniel's comment about how to describe or talk about the state and not necessarily advocating that view. But to your question, like it or not, I think the API encourages this way of thinking because the get() method is on the ContextVar itself, and so it's the ContextVar which is doing the looking up rather than just fulfilling the role of a key name. The API brings to mind other containers and things holding values like dict.get(), queue.get(), BytesIO.getvalue(), and container type's object.__getitem__(), etc. So I think one will need to be prepared for many or most users having this conception with the current API. (I think renaming to something like ContextVar.lookup() or even ContextVar.value() would go a long way towards dispelling that, but Guido said earlier in the thread that he likes the shorter name.) > Do Python variables hold/envelope objects they reference? No, they > don't. They are simple names and are used to lookup objects in > globals/locals dicts. ContextVars are very similar! They are *keys* > in Context objects—that is it. Python variables don't hold the objects. But the analogy also doesn't quite match because variables also don't have get() methods. It's Python which is doing the looking up in that case rather than the variable itself. With ContextVars, it's serving both roles of name and thing doing the looking up. This is one reason why I suggested several days ago that I thought something like contextvars.get(key) (where key is a ContextVar) would be a less confusing API. That way the ContextVar / ContextKey(?) would only be acting as a key and not also be responsible for doing the lookup and knowing about what is containing it. --Chris > > ContextVar.default is returned by ContextVar.get() when it cannot find > the value for the context variable in the current Context object. If > ContextVar.default was not provided, a LookupError is raised. > > The reason why this is simpler for regular variables is because they > have a dedicated syntax. Instead of writing > > print(globals()['some_variable']) > > we simply write > > print(some_variable) > > Similarly for context variables, we could have written: > >print(copy_context()[var]) > > But instead we use a ContextVar.get(): > >print(var.get()) > > If we had a syntax support for context variables, it would be like this: > >context var >print(var) # Lookups 'var' in the current context > > Although I very much doubt that we would *ever* want to have a > dedicated syntax for context variables (they are very niche and are > only needed in some very special cases), I hope that this line of > thinking would help to clear the waters. > > 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
Re: [Python-Dev] PEP 567 pre v3
On Thu, Jan 11, 2018 at 10:35 AM, Chris Jerdonek wrote: > On Mon, Jan 8, 2018 at 11:02 PM, Nathaniel Smith wrote: >> Right now, the set of valid states for a ContextVar are: it can hold >> any Python object, or it can be undefined. However, the only way it >> can be in the "undefined" state is in a new Context where it has never >> had a value; once it leaves the undefined state, it can never return >> to it. > > I know Yury responded to one aspect of this point later on in the > thread. However, in terms of describing the possible states without > reference to the internal Context mappings, IIUC, wouldn't it be more > accurate to view a ContextVar as a stack of values rather than just > the binary "holding an object or not"? This is to reflect the number > of times set() has been called (and so the number of times reset() > would need to be called to "empty" the ContextVar). But why do you want to think of ContextVar as a stack of values? Or as something that is holding even one value? Do Python variables hold/envelope objects they reference? No, they don't. They are simple names and are used to lookup objects in globals/locals dicts. ContextVars are very similar! They are *keys* in Context objects—that is it. ContextVar.default is returned by ContextVar.get() when it cannot find the value for the context variable in the current Context object. If ContextVar.default was not provided, a LookupError is raised. The reason why this is simpler for regular variables is because they have a dedicated syntax. Instead of writing print(globals()['some_variable']) we simply write print(some_variable) Similarly for context variables, we could have written: print(copy_context()[var]) But instead we use a ContextVar.get(): print(var.get()) If we had a syntax support for context variables, it would be like this: context var print(var) # Lookups 'var' in the current context Although I very much doubt that we would *ever* want to have a dedicated syntax for context variables (they are very niche and are only needed in some very special cases), I hope that this line of thinking would help to clear the waters. 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
Re: [Python-Dev] PEP 567 pre v3
On Thu, Jan 11, 2018 at 10:39 AM, Ethan Furman wrote: > On 01/10/2018 10:23 PM, Yury Selivanov wrote: [..] >> Therefore I'm still in favour of keeping the current PEP 567 >> behaviour. > > > To be clear: We'll now be able to specify a default when we create the > variable, but we can also leave it out so a LookupError can be raised later? Correct. 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
Re: [Python-Dev] PEP 567 pre v3
On 01/10/2018 10:23 PM, Yury Selivanov wrote: On Thu, Jan 11, 2018 at 4:44 AM, Nathaniel Smith wrote: It may have gotten lost in that email, but my actual favorite approach is that we make the signatures: ContextVar(name, *, initial_value) # or even (*, name, initial_value) ContextVar.get() ContextVar.set(value) so that when you create a ContextVar you always state the initial value, whatever makes sense in a particular case. (Obviously None will be a very popular choice, but this way it won't be implicit, and no-one will be surprised to see it returned from get().) Alright, you've shown that most of the time when we use threading.local in the standard library we subclass it in order to provide a default value (and avoid AttributeError being thrown). This is a solid argument in favour of keeping the 'default' parameter for the ContextVar constructor. Let's keep it. [...] I think that when you have an int stored in a context variable it would usually make sense to give it a 0 default (or some other number). However, for a complex object (like current request object) there is *no* sensible default value sometimes. Forcing the user to set it to None feels like a badly designed API that forces the user to work around it. Therefore I'm still in favour of keeping the current PEP 567 behaviour. To be clear: We'll now be able to specify a default when we create the variable, but we can also leave it out so a LookupError can be raised later? -- ~Ethan~ ___ 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
Re: [Python-Dev] PEP 567 pre v3
On Mon, Jan 8, 2018 at 11:02 PM, Nathaniel Smith wrote: > Right now, the set of valid states for a ContextVar are: it can hold > any Python object, or it can be undefined. However, the only way it > can be in the "undefined" state is in a new Context where it has never > had a value; once it leaves the undefined state, it can never return > to it. I know Yury responded to one aspect of this point later on in the thread. However, in terms of describing the possible states without reference to the internal Context mappings, IIUC, wouldn't it be more accurate to view a ContextVar as a stack of values rather than just the binary "holding an object or not"? This is to reflect the number of times set() has been called (and so the number of times reset() would need to be called to "empty" the ContextVar). --Chris > > This makes me itch. It's very weird to have a mutable variable with a > valid state that you can't reach by mutating it. I see two > self-consistent ways to make me stop itching: (a) double-down on > undefined as being part of ContextVar's domain, or (b) reduce the > domain so that undefined is never a valid state. > > # Option 1 > > In the first approach, we conceptualize ContextVar as being a > container that either holds a value or is empty (and then there's one > of these containers for each context). We also want to be able to > define an initial value that the container takes on when a new context > materializes, because that's really convenient. And then after that we > provide ways to get the value (if present), or control the value > (either set it to a particular value or unset it). So something like: > > var1 = ContextVar("var1") # no initial value > var2 = ContextVar("var2", initial_value="hello") > > with assert_raises(SomeError): > var1.get() > # get's default lets us give a different outcome in cases where it > would otherwise raise > assert var1.get(None) is None > assert var2.get() == "hello" > # If get() doesn't raise, then the argument is ignored > assert var2.get(None) == "hello" > > # We can set to arbitrary values > for var in [var1, var2]: > var.set("new value") > assert var.get() == "new value" > > # We can unset again, so get() will raise > for var in [var1, var2]: > var.unset() > with assert_raises(SomeError): > var.get() > assert var.get(None) is None > > To fulfill all that, we need an implementation like: > > MISSING = make_sentinel() > > class ContextVar: > def __init__(self, name, *, initial_value=MISSING): > self.name = name > self.initial_value = initial_value > > def set(self, value): > if value is MISSING: raise TypeError > current_context()._dict[self] = value > # Token handling elided because it's orthogonal to this issue > return Token(...) > > def unset(self): > current_context()._dict[self] = MISSING > # Token handling elided because it's orthogonal to this issue > return Token(...) > > def get(self, default=_NOT_GIVEN): > value = current_context().get(self, self.initial_value) > if value is MISSING: > if default is _NOT_GIVEN: > raise ... > else: > return default > else: > return value > > Note that the implementation here is somewhat tricky and non-obvious. > In particular, to preserve the illusion of a simple container with an > optional initial value, we have to encode a logically undefined > ContextVar as one that has Context[var] set to MISSING, and a missing > entry in Context encodes the presence of the inital value. If we > defined unset() as 'del current_context._dict[self]', then we'd have: > > var2.unset() > assert var2.get() is None > > which would be very surprising to users who just want to think about > ContextVars and ignore all that stuff about Contexts. This, in turn, > means that we need to expose the MISSING sentinel in general, because > anyone introspecting Context objects directly needs to know how to > recognize this magic value to interpret things correctly. > > AFAICT this is the minimum complexity required to get a complete and > internally-consistent set of operations for a ContextVar that's > conceptualized as being a container that either holds an arbitrary > value or is empty. > > # Option 2 > > The other complete and coherent conceptualization I see is to say that > a ContextVar always holds a value. If we eliminate the "unset" state > entirely, then there's no "missing unset method" -- there just isn't > any concept of an unset value in the first place, so there's nothing > to miss. This idea shows up in lots of types in Python, actually -- > e.g. for any exception object, obj.__context__ is always defined. Its > value might be None, but it has a value. In this approach, > ContextVar's are similar. > > To fulfill all that, we need an implementation like: > > class ContextVar: > # Or maybe it'd be better to ma
Re: [Python-Dev] PEP 567 pre v3
On Thu, Jan 11, 2018 at 4:44 AM, Nathaniel Smith wrote: [..] > It may have gotten lost in that email, but my actual favorite approach > is that we make the signatures: > > ContextVar(name, *, initial_value) # or even (*, name, initial_value) > ContextVar.get() > ContextVar.set(value) > > so that when you create a ContextVar you always state the initial > value, whatever makes sense in a particular case. (Obviously None will > be a very popular choice, but this way it won't be implicit, and > no-one will be surprised to see it returned from get().) Alright, you've shown that most of the time when we use threading.local in the standard library we subclass it in order to provide a default value (and avoid AttributeError being thrown). This is a solid argument in favour of keeping the 'default' parameter for the ContextVar constructor. Let's keep it. However I still don't like the idea of making defaults mandatory. I have at least one exemplary use case (I can come up with more of such examples, btw) which shows that it's not always desired to have a None default: getting the current request object in a web application. With the current PEP 567 semantics: request_var: ContextVar[Request] = ContextVar('current_request') and later: request : Request = request_var.get() 'request_var.get()' will throw a LookupError, which will indicate that something went wrong in the framework layer. The user should never see this error, and they can just rely on the fact that the current request is always available (cannot be None). With mandatory defaults, the type of 'request' variable will be 'Optional[Request]', and the user will be forced to add an 'if' statement to guard against None values. Otherwise the user risks having occasional AttributeErrors that don't really explain what actually happened. I would prefer them to see a LookupError('cannot lookup current_request context variable') instead. I think that when you have an int stored in a context variable it would usually make sense to give it a 0 default (or some other number). However, for a complex object (like current request object) there is *no* sensible default value sometimes. Forcing the user to set it to None feels like a badly designed API that forces the user to work around it. Therefore I'm still in favour of keeping the current PEP 567 behaviour. It feels very consistent with how variable lookups and threading.local objects work in Python now. 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
Re: [Python-Dev] PEP 567 pre v3
On 11 January 2018 at 10:44, Nathaniel Smith wrote: > It may have gotten lost in that email, but my actual favorite approach > is that we make the signatures: > > ContextVar(name, *, initial_value) # or even (*, name, initial_value) > ContextVar.get() > ContextVar.set(value) > > so that when you create a ContextVar you always state the initial > value, whatever makes sense in a particular case. (Obviously None will > be a very popular choice, but this way it won't be implicit, and > no-one will be surprised to see it returned from get().) I also like this idea, and I think it aligns better with "dict.get" than it may first appear: the trick is that in this simplified API "ContextVar.get()" would be akin to "get_thread_state().current_context.get(cv, cv.initial_value)" (and PEP 568 wouldn't really change that). So both the key and the default value are specified at ContextVar initialisation time, and if you want to supply a non-standard default, then you need to break the ContextVar abstraction, and access "contextvars.copy_context().get(cv, custom_default)" instead. If we later decide that we do want to support raising an exception for unitialised access after all, then we could introduce a "missing" callback to the ContextVar constructor that would be akin to defaultdict's "default_factory" callback (with the requirement becoming that you have to specify either an initial_value, or a missing callback, but not both). Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ 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
Re: [Python-Dev] PEP 567 pre v3
On Tue, Jan 9, 2018 at 3:41 AM, Yury Selivanov wrote: > On Tue, Jan 9, 2018 at 11:02 AM, Nathaniel Smith wrote: >> Right now, the set of valid states for a ContextVar are: it can hold >> any Python object, or it can be undefined. However, the only way it >> can be in the "undefined" state is in a new Context where it has never >> had a value; once it leaves the undefined state, it can never return >> to it. > > Is "undefined" a state when a context variable doesn't have a default > and isn't yet set? If so, why can't it be returned back to the > "undefined" state? That's why we have the 'reset' method: Sorry, yes, you can return to the "undefined" state if you have a valid token that hasn't been used yet. But my point is that it's weird to have a variable that needs so many words to describe which kinds of state transitions are possible. > I don't like how context variables are defined in Option 1 and Option > 2. I view ContextVars as keys in some global context mapping--akin to > Python variables. This is one totally reasonable option but, I mean... it's software, there are lots of options for how to view things that we could potentially make true, and we get to pick the one that works best :-). And I think it's easier to explain to users how ContextVar works if we can do it without talking about Context mappings etc. Thread-local storage is also implemented using some per-thread maps and various clever tricks, but I don't think I've ever seen documentation that described it that way. > In any case, at this point I think that the best option is to simply > drop the "default" parameter from the ContextVar constructor. This > would leave us with only one default in ContextVar.get() method: > > c.get() # Will raise a LookupError if 'c' is not set > c.get('python') # Will return 'python' if 'c' is not set > > I also now see how having two different 'default' values: one defined > when a ContextVar is created, and one can be passed to > ContextVar.get() is confusing. But the constructor default is way more important for usability than any of the other features we're talking about! Every time I use threading.local, I get annoyed that there isn't a simpler way to specify a default value. OTOH I've never found a case where I actually wanted undefined values. To find out whether my experience is typical, I did a quick grep of the stdlib, and found 5 thread local variables: - asyncio.events._BaseEventLoopPolicy._local.{_loop, _set_called}: These two use the 'subclass threading.local' trick to make it seem like these are initialized to None. - asyncio.events._running_loop: This uses the subclass trick to to make it seem like it's initialized to (None, None). - multiprocessing.context._tls.spawning_popen: Here the code defines two accessors (get_spawning_popen, set_spawning_popen) that make it seem like it's initialized to None. Of course you could do this with ContextVar's too, but if ContextVar had native support for specifying an initial value then they'd be unnecessary, because spawning_popen.get()/set() would already do the right thing. - _pydecimal.local.__decimal_context__: This is a little trickier. It has a default value, but it's mutable, so access is hidden behind two accessors (getcontext, setcontext) and it's initialized on first access. Currently this is done with a try: except:, but if thread locals had the ability to set the default to None, then using that would make the implementation shorter and faster (exceptions are expensive). So that's 5 out of 5 cases where the code would get simpler if thread-locals had the ability to specify a default initial value, 0 out of 5 cases where anyone would miss support for undefined values or wants to be able to control the default get() value on a call-by-call basis. The argument for supporting undefined values in ContextVar is mostly by analogy with regular Python variables. I like analogies, but I don't think we should sacrifice actual use cases to preserve the analogy. > But I'd be -1 on making all ContextVars have a None default > (effectively have a "ContextVar.get(default=None)" signature. This > would be a very loose semantics in my opinion. It may have gotten lost in that email, but my actual favorite approach is that we make the signatures: ContextVar(name, *, initial_value) # or even (*, name, initial_value) ContextVar.get() ContextVar.set(value) so that when you create a ContextVar you always state the initial value, whatever makes sense in a particular case. (Obviously None will be a very popular choice, but this way it won't be implicit, and no-one will be surprised to see it returned from get().) -n -- Nathaniel J. Smith -- https://vorpus.org ___ 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
Re: [Python-Dev] Bug report in audioop module.
On 2018-01-10 20:37, Moses Egypt wrote: I was told to post this here when I asked what to do on the python reddit. This is the issue: https://bugs.python.org/issue32004 It has received no response since I posted it two months ago, so I figured I didn't fill something out correctly to get it put on someone's tracker. This is my first bug report, so please let me know if there is anything I need to do get it appointed to the correct person next time. Thanks. This is open source; nothing gets done unless someone chooses to do it, usually because it "scratches their itch" or they have a problem and no-one else is interested in doing it. If you don't get any response, you could always try fixing it yourself. ___ 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
Re: [Python-Dev] Bug report in audioop module.
On 11 January 2018 at 06:37, Moses Egypt wrote: > I was told to post this here when I asked what to do on the python reddit. > This is the issue: > https://bugs.python.org/issue32004 Thank you for taking the time to file that! > It has received no response since I posted it two months ago, so I figured I > didn't fill something out correctly to get it put on someone's tracker. This > is my first bug report, so please let me know if there is anything I need to > do get it appointed to the correct person next time. Thanks. You've actually done everything right - it's just hit or miss as to whether or not issues will attract a core developer's attention. (Unfortunately there aren't currently any jobs in the world that have "Help limit the growth of the CPython issue count in general" as a requirement, so there aren't any kind of consistent response time assurance for issues or pull requests). Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ 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
Re: [Python-Dev] PEP 567 v2
On Tue, Jan 9, 2018 at 2:59 AM, Yury Selivanov wrote: > > >> On Jan 9, 2018, at 11:18 AM, Nathaniel Smith wrote: >> The approach I took in PEP 568 is even simpler, I think. The PEP is a >> few pages long because I wanted to be exhaustive to make sure we >> weren't missing any details, but the tl;dr is: The ChainMap lives >> entirely inside the threadstate, so there's no need to create a LC/EC >> distinction -- users just see Contexts, or there's the one stack >> introspection API, get_context_stack(), which returns a List[Context]. >> Instead of messing with new_child, copy_context is just >> Context(dict(chain_map)) -- i.e., it creates a flattened copy of the >> current mapping. (If we used new_child, then we'd have to have a way >> to return a ChainMap, reintroducing the LC/EC mess. > > This sounds reasonable. Although keep in mind that merging hamt is still an > expensive operation, so flattening shouldn't always be performed (this is > covered in 550). Right, the PEP mostly focuses on the semantics rather than the implementation and this is an implementation detail (the user can't tell whether a Context internally holds a stack of HAMTs or just one). But there is a note that we might choose to perform the actual flattening lazily if it turns out to be worthwhile. > I also wouldn't call LC/EC a "mess". Your pep just names things differently, > but otherwise is entirely built on concepts and ideas introduced in pep 550. Sorry for phrasing it like that -- I just meant that at the API level, the LC/EC split caused a lot of confusion (and apparently this was it's "nail in the coffin"!). In the PEP 567/568 version, the underlying concepts are the same, but the API ends up being simpler. -n -- Nathaniel J. Smith -- https://vorpus.org ___ 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
[Python-Dev] Bug report in audioop module.
I was told to post this here when I asked what to do on the python reddit. This is the issue: https://bugs.python.org/issue32004 It has received no response since I posted it two months ago, so I figured I didn't fill something out correctly to get it put on someone's tracker. This is my first bug report, so please let me know if there is anything I need to do get it appointed to the correct person next time. Thanks. ___ 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
Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568
I'm sorry, Koos, but based on your past contributions I am not interested in discussing this topic with you. On Wed, Jan 10, 2018 at 8:58 AM, Koos Zevenhoven wrote: > The status of PEP 555 is just a side track. Here, I took a step back > compared to what went into PEP 555. > > —Koos > > > On Wed, Jan 10, 2018 at 6:21 PM, Guido van Rossum > wrote: > >> The current status of PEP 555 is "Withdrawn". I have no interest in >> considering it any more, so if you'd rather see a decision from me I'll be >> happy to change it to "Rejected". >> >> On Tue, Jan 9, 2018 at 10:29 PM, Koos Zevenhoven >> wrote: >> >>> On Jan 10, 2018 07:17, "Yury Selivanov" wrote: >>> >>> Wasn't PEP 555 rejected by Guido? What's the point of this post? >>> >>> >>> I sure hope there is a point. I don't think mentioning PEP 555 in the >>> discussions should hurt. >>> >>> A typo in my post btw: should be "PEP 567 (+568 ?)" in the second >>> paragraph of course. >>> >>> -- Koos (mobile) >>> >>> >>> Yury >>> >>> On Wed, Jan 10, 2018 at 4:08 AM Koos Zevenhoven >>> wrote: >>> Hi all, I feel like I should write some thoughts regarding the "context" discussion, related to the various PEPs. I like PEP 567 (+ 567 ?) better than PEP 550. However, besides providing cvar.set(), I'm not really sure about the gain compared to PEP 555 (which could easily have e.g. a dict-like interface to the context). I'm still not a big fan of "get"/"set" here, but the idea was indeed to provide those on top of a PEP 555 type thing too. "Tokens" in PEP 567, seems to resemble assignment context managers in PEP 555. However, they feel a bit messy to me, because they make it look like one could just set a variable and then revert the change at any point in time after that. PEP 555 is in fact a simplification of my previous sketch that had a .set(..) in it, but was somewhat different from PEP 550. 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: # Version A: cvar.set(1) with context_scope(): cvar.set(2) assert cvar.get() == 2 assert cvar.get() == 1 Then I added the ability to define scopes for different variables separately: # Version B cvar1.set(1) cvar2.set(2) with context_scope(cvar1): cvar1.set(11) cvar2.set(22) assert cvar1.get() == 1 assert cvar2.get() == 22 However, in practice, most libraries would wrap __enter__, set and __exit__ into another context manager. So maybe one might want to allow something like # Version C: assert cvar.get() == something with context_scope(cvar, 2): assert cvar.get() == 2 assert cvar.get() == something But this then led to combining "__enter__" and ".set(..)" into Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this: # PEP 555 draft version: assert cvar.value == something with cvar.assign(1): assert cvar.value == 1 assert cvar.value == something 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. -- Koos ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailma n/options/python-dev/yselivanov.ml%40gmail.com >>> >>> >>> ___ >>> Python-Dev mailing list >>> Python-Dev@python.org >>> https://mail.python.org/mailman/listinfo/python-dev >>> Unsubscribe: https://mail.python.org/mailma >>> n/options/python-dev/guido%40python.org >>> >>> >> >> >> -- >> --Guido van Rossum (python.org/~guido) >> > > > > -- > + Koos Zevenhoven + http://twitter.com/k7hoven + > -- --Guido van Rossum (python.org/~guido) ___ 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
Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568
The status of PEP 555 is just a side track. Here, I took a step back compared to what went into PEP 555. —Koos On Wed, Jan 10, 2018 at 6:21 PM, Guido van Rossum wrote: > The current status of PEP 555 is "Withdrawn". I have no interest in > considering it any more, so if you'd rather see a decision from me I'll be > happy to change it to "Rejected". > > On Tue, Jan 9, 2018 at 10:29 PM, Koos Zevenhoven > wrote: > >> On Jan 10, 2018 07:17, "Yury Selivanov" wrote: >> >> Wasn't PEP 555 rejected by Guido? What's the point of this post? >> >> >> I sure hope there is a point. I don't think mentioning PEP 555 in the >> discussions should hurt. >> >> A typo in my post btw: should be "PEP 567 (+568 ?)" in the second >> paragraph of course. >> >> -- Koos (mobile) >> >> >> Yury >> >> On Wed, Jan 10, 2018 at 4:08 AM Koos Zevenhoven >> wrote: >> >>> Hi all, >>> >>> I feel like I should write some thoughts regarding the "context" >>> discussion, related to the various PEPs. >>> >>> I like PEP 567 (+ 567 ?) better than PEP 550. However, besides providing >>> cvar.set(), I'm not really sure about the gain compared to PEP 555 (which >>> could easily have e.g. a dict-like interface to the context). I'm still not >>> a big fan of "get"/"set" here, but the idea was indeed to provide those on >>> top of a PEP 555 type thing too. >>> >>> "Tokens" in PEP 567, seems to resemble assignment context managers in >>> PEP 555. However, they feel a bit messy to me, because they make it look >>> like one could just set a variable and then revert the change at any point >>> in time after that. >>> >>> PEP 555 is in fact a simplification of my previous sketch that had a >>> .set(..) in it, but was somewhat different from PEP 550. 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: >>> >>> # Version A: >>> cvar.set(1) >>> with context_scope(): >>> cvar.set(2) >>> >>> assert cvar.get() == 2 >>> >>> assert cvar.get() == 1 >>> >>> Then I added the ability to define scopes for different variables >>> separately: >>> >>> # Version B >>> cvar1.set(1) >>> cvar2.set(2) >>> with context_scope(cvar1): >>> cvar1.set(11) >>> cvar2.set(22) >>> >>> assert cvar1.get() == 1 >>> assert cvar2.get() == 22 >>> >>> >>> However, in practice, most libraries would wrap __enter__, set and >>> __exit__ into another context manager. So maybe one might want to allow >>> something like >>> >>> # Version C: >>> assert cvar.get() == something >>> with context_scope(cvar, 2): >>> assert cvar.get() == 2 >>> >>> assert cvar.get() == something >>> >>> >>> But this then led to combining "__enter__" and ".set(..)" into >>> Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this: >>> >>> # PEP 555 draft version: >>> assert cvar.value == something >>> with cvar.assign(1): >>> assert cvar.value == 1 >>> >>> assert cvar.value == something >>> >>> >>> 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. >>> >>> -- Koos >>> >>> ___ >>> Python-Dev mailing list >>> Python-Dev@python.org >>> https://mail.python.org/mailman/listinfo/python-dev >>> Unsubscribe: https://mail.python.org/mailma >>> n/options/python-dev/yselivanov.ml%40gmail.com >>> >> >> >> ___ >> 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/guido% >> 40python.org >> >> > > > -- > --Guido van Rossum (python.org/~guido) > -- + Koos Zevenhoven + http://twitter.com/k7hoven + ___ 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
Re: [Python-Dev] Thoughts on "contexts". PEPs 550, 555, 567, 568
The current status of PEP 555 is "Withdrawn". I have no interest in considering it any more, so if you'd rather see a decision from me I'll be happy to change it to "Rejected". On Tue, Jan 9, 2018 at 10:29 PM, Koos Zevenhoven wrote: > On Jan 10, 2018 07:17, "Yury Selivanov" wrote: > > Wasn't PEP 555 rejected by Guido? What's the point of this post? > > > I sure hope there is a point. I don't think mentioning PEP 555 in the > discussions should hurt. > > A typo in my post btw: should be "PEP 567 (+568 ?)" in the second > paragraph of course. > > -- Koos (mobile) > > > Yury > > On Wed, Jan 10, 2018 at 4:08 AM Koos Zevenhoven wrote: > >> Hi all, >> >> I feel like I should write some thoughts regarding the "context" >> discussion, related to the various PEPs. >> >> I like PEP 567 (+ 567 ?) better than PEP 550. However, besides providing >> cvar.set(), I'm not really sure about the gain compared to PEP 555 (which >> could easily have e.g. a dict-like interface to the context). I'm still not >> a big fan of "get"/"set" here, but the idea was indeed to provide those on >> top of a PEP 555 type thing too. >> >> "Tokens" in PEP 567, seems to resemble assignment context managers in PEP >> 555. However, they feel a bit messy to me, because they make it look like >> one could just set a variable and then revert the change at any point in >> time after that. >> >> PEP 555 is in fact a simplification of my previous sketch that had a >> .set(..) in it, but was somewhat different from PEP 550. 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: >> >> # Version A: >> cvar.set(1) >> with context_scope(): >> cvar.set(2) >> >> assert cvar.get() == 2 >> >> assert cvar.get() == 1 >> >> Then I added the ability to define scopes for different variables >> separately: >> >> # Version B >> cvar1.set(1) >> cvar2.set(2) >> with context_scope(cvar1): >> cvar1.set(11) >> cvar2.set(22) >> >> assert cvar1.get() == 1 >> assert cvar2.get() == 22 >> >> >> However, in practice, most libraries would wrap __enter__, set and >> __exit__ into another context manager. So maybe one might want to allow >> something like >> >> # Version C: >> assert cvar.get() == something >> with context_scope(cvar, 2): >> assert cvar.get() == 2 >> >> assert cvar.get() == something >> >> >> But this then led to combining "__enter__" and ".set(..)" into >> Assignment.__enter__ -- and "__exit__" into Assignment.__exit__ like this: >> >> # PEP 555 draft version: >> assert cvar.value == something >> with cvar.assign(1): >> assert cvar.value == 1 >> >> assert cvar.value == something >> >> >> 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. >> >> -- Koos >> >> ___ >> 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/yselivano >> v.ml%40gmail.com >> > > > ___ > 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/ > guido%40python.org > > -- --Guido van Rossum (python.org/~guido) ___ 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
Re: [Python-Dev] Best Python API for exposing posix_spawn
I think I really like Antoine's suggestion so I'm going to finish implementing it that way. I think this keeps the API simple, does not bring in the os module new dependencies, keeps the C implementation clean and is consistent with the rest of the posix module. I will post an update when is ready. Thank you everyone for sharing your view and advice! ___ 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