Re: [Python-Dev] the current behavior of try: ... finally:
It did surprise me also. Because I've come to Python from Delphi. There are no return statement in Delphi. I also write some c++, the language has no finally-statement. This problem probably python exclusive. I think it's not too difficult to get used to it. This behavior is fine for me. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Tidier Exceptions
[Greg Ewing] Are there plans as to when string exceptions will be exterminated? Surely the only places they're used now are in some very old library modules. No concrete plans; I was always planning to abandon them in 3.0 but haven't felt the need to do it sooner. Last I looked Zope 2 still depended on them (especially in the bowels of ZODB); maybe Tim Peters knows if that's still the case. If you want to do it sooner, maybe we need a small PEP with the timeline (e.g. warn in Python 2.5, illegal in Python 2.6). Or perhaps a patch on SF is all that's needed. I expect it would be much more challenging to switch to the model where all exceptions derive from a single (new-style) base class. (And no, there are no plans to kill classic classes before 3.0 either.) -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] with use case: replacing a file
Guido van Rossum wrote: P.S. The points regarding non-local flow control in Joel Spolsky's latest Joel on Software article (especially the links at the end) may have had something to do with my change of heart. . . I'm a big fan of Joel. Care to share the specific URL for the article you're referring to? Sorry about that (I was in a hurry this morning). It was here: http://www.joelonsoftware.com/articles/Wrong.html The link of particular interest regarding exception handling was this one: http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx Some interesting points about some of the cons of exception based code (at least some of which relate to what we're dealing with in factoring out finally clauses, and C++ deals with via scope-based destruction). Anyway, it made me realise that having any callables you invoke potentially raise exceptions is already tricky to deal with, and allowing a different call to potentially *suppress* those exceptions is a recipe for serious confusion. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
I just read Raymond Chen's rant against control flow macros: http://blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx I think this pretty much kills PEP 340, as well as Nick Coghlan's alternative: both proposals let you write a template that can be used to hide exception-catching code, which is a form of control flow (and a pretty important one if you read Chen's rant against exceptions referenced by the former, even if you don't agree with everything he says in the latter). Which leaves us, IMO, with the choice between PEP 310 and my own PEP-340-redux proposal; these *only* introduce a finally-clause, which does not affect the control flow. I'm not counting exceptions that might happen in the finally-clause; exceptions can happen anywhere anyway. But I am counting the *catching* of an exception as control flow, since that means that code past BLOCK (in the same function) is reachable even if BLOCK was not executed to completion; and this is the argument against PEP 340 and against Nick's alternative. Let's compare and contrast the two remaining competitors: PEP 310 === Syntax: with EXPR [= VAR]: BLOCK Translation: [VAR =] abc = EXPR if hasattr(abc, __enter__): abc.__enter__() try: BLOCK finally: abc.__exit__() Pros: - dead simple Cons: - can't use a decorated generator for EXPR PEP 340 redux = Syntax: do EXPR [as VAR]: BLOCK Translation: abc = EXPR [VAR =] abc.__enter__() try: BLOCK finally: abc.__exit__(*sys.exc_info()) # Not exactly Pros: - can use a decorated generator as EXPR - separation of EXPR and VAR (VAR gets what EXPR.__enter__() returns) Cons: - slightly less simple (__enter__ must return something for VAR; __exit__ takes optional args) Everything else is equal or can be made equal. We can make them more equal by treating the arguments passed to __exit__() as a separate decision, and waffling about whether __enter__() should be optional (I think it's a bad idea even for PEP 310; it *could* be made optional for PEP 340 redux). Let's also not quibble about the keyword used; again, that can be a separate decision. Note that only PEP 310 can use the VAR = EXPR syntax; PEP 340 redux *must* use EXPR as VAR since it doesn't assign the value of EXPR to VAR; PEP 310 can be rewritten using this syntax as well. So then the all-important question I want to pose is: do we like the idea of using a (degenerate, decorated) generator as a template for the do-statement enough to accept the slightly increased complexity? The added complexity is caused by the need to separate VAR from EXPR so that a generator can be used. I personally like this separation; I actually like that the anonymous block controller is logically separate from the variable bound by the construct. From Greg Ewing's response to the proposal to endow file objects with __enter__ and __exit__ methods, I believe he thinks so too. Straight up-or-down votes in the full senate are appreciated at this point. On to the secondary questions: - Today I like the 'do' keyword better; 'with' might confuse folks coming from Pascal or VB - I have a more elaborate proposal for __exit__'s arguments. Let the translation be as follows: abc = EXPR [VAR =] abc.__enter__() oke = False # Pronounced okay exc = () try: try: BLOCK oke = True except: exc = sys.exc_info() raise finally: abc.__exit__(oke, *exc) This means that __exit__ can be called with the following arguments: abc.__exit__(True) - normal completion of BLOCK abc.__exit__(False) - BLOCK was left by a non-local goto (break/continue/return) abc.__exit__(False, t, v, tb) - BLOCK was left by an exception (An alternative would be to always call it with 4 arguments, the last three being None in the first two cases.) If we adopt PEP 340 redux, it's up to the decorator for degenerate generators to decide how to pass this information into the generator; if we adopt PEP 342 (continue EXPR) at the same time, we can let the yield-expression return a 4-tuple (oke, t, v, tb). Most templates can ignore this information (so they can just use a yield-statement). PS. I've come up with another interesting use case: block signals for the duration of a block. This could be a function in the signal module, e.g. signal.blocking([ist of signals to block]). The list would default to all signals. Similar signal.ignoring(). -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] with use case: replacing a file
At 07:23 PM 5/13/2005 +1000, Nick Coghlan wrote: Guido van Rossum wrote: P.S. The points regarding non-local flow control in Joel Spolsky's latest Joel on Software article (especially the links at the end) may have had something to do with my change of heart. . . I'm a big fan of Joel. Care to share the specific URL for the article you're referring to? Sorry about that (I was in a hurry this morning). It was here: http://www.joelonsoftware.com/articles/Wrong.html Wrong is an excellent title for that article; it's completely wrongheaded about exceptions. :) Great basic idea (make wrong code look wrong), but for all practical purposes the actual specific advice in the article is only meaningful for C, where you can't create real types and there are no exceptions. In Python, there are *much* saner solutions to his strawman problems. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Guido van Rossum [EMAIL PROTECTED] writes: I just read Raymond Chen's rant against control flow macros: http://blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx I think this pretty much kills PEP 340, as well as Nick Coghlan's alternative: both proposals let you write a template that can be used to hide exception-catching code, which is a form of control flow (and a pretty important one if you read Chen's rant against exceptions referenced by the former, even if you don't agree with everything he says in the latter). Well, I'm not sure what the content of the latter article is, other than getting things right can be hard. BTW, the else: on try statements is so very handy for getting this sort of thing (more) corrent. Which leaves us, IMO, with the choice between PEP 310 and my own PEP-340-redux proposal; these *only* introduce a finally-clause, which does not affect the control flow. I'm not counting exceptions that might happen in the finally-clause; exceptions can happen anywhere anyway. But I am counting the *catching* of an exception as control flow, since that means that code past BLOCK (in the same function) is reachable even if BLOCK was not executed to completion; and this is the argument against PEP 340 and against Nick's alternative. Let's compare and contrast the two remaining competitors: PEP 310 === Syntax: with EXPR [= VAR]: BLOCK Translation: [VAR =] abc = EXPR if hasattr(abc, __enter__): abc.__enter__() try: BLOCK finally: abc.__exit__() Pros: - dead simple Cons: - can't use a decorated generator for EXPR Sorry, why not? [note: I work this out, below, but I still think the code is worth posting] import sys class BlockTemplate(object): def __init__(self, g, args, kw): self.g = g self.args = args self.kw = kw def __enter__(self): self.giter = self.g(*self.args) self.giter.next() def __exit__(self): try: self.giter.next() except StopIteration: pass else: raise RuntimeError, generator not exhausted def template(g): def _(*args, **kw): return BlockTemplate(g, args, kw) return _ @template def redirected_stdout(out): print 'hi' save_stdout = sys.stdout sys.stdout = out yield None sys.stdout = save_stdout print 'ho' ## with redirected_stdout(fileobj): ## print 1 output = open(foo, w) abc = redirected_stdout(output) abc.__enter__() try: print 1 finally: abc.__exit__() output.close() print repr(open(foo).read()) (this was a bit harder to get right than I expected, mind). Oh, I guess the point is that with a decorated generator you can yield a value to be used as VAR, rather than just discarding the value as here. Hmm. PEP 340 redux = Syntax: do EXPR [as VAR]: BLOCK Translation: abc = EXPR [VAR =] abc.__enter__() try: BLOCK finally: abc.__exit__(*sys.exc_info()) # Not exactly These two expansions look very similar to me. What am I missing? Pros: - can use a decorated generator as EXPR - separation of EXPR and VAR (VAR gets what EXPR.__enter__() returns) Oh! Hmm. This is a bit subtle. I guess I should think about some examples. Cons: - slightly less simple (__enter__ must return something for VAR; __exit__ takes optional args) If things were fiddled such that sys.exc_info() return non-Nones when a finally clause is being executed because of an exception, we don't really need this wart, do we? Everything else is equal or can be made equal. We can make them more equal by treating the arguments passed to __exit__() as a separate decision, and waffling about whether __enter__() should be optional (I think it's a bad idea even for PEP 310; it *could* be made optional for PEP 340 redux). I don't really recall why it's optional in PEP 310. Let's also not quibble about the keyword used; again, that can be a separate decision. Note that only PEP 310 can use the VAR = EXPR syntax; PEP 340 redux *must* use EXPR as VAR since it doesn't assign the value of EXPR to VAR; PEP 310 can be rewritten using this syntax as well. So then the all-important question I want to pose is: do we like the idea of using a (degenerate, decorated) generator as a template for the do-statement enough to accept the slightly increased complexity? Looking at my above code, no (even though I think I've rendered the point moot...). Compare and contrast: @template def redirected_stdout(out): save_stdout = sys.stdout sys.stdout = out yield None sys.stdout = save_stdout class redirected_stdout(object): def __init__(self, output): self.output = output def __enter__(self): self.save_stdout = sys.stdout sys.stdout = self.output def __exit__(self): sys.stdout = self.save_stdout The former is shorter and contains less (well, no)
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
At 03:05 AM 5/13/2005 -0700, Guido van Rossum wrote: So then the all-important question I want to pose is: do we like the idea of using a (degenerate, decorated) generator as a template for the do-statement enough to accept the slightly increased complexity? Since the do protocol is now distinct from the iterator protocol, I don't believe a decorator is still required. The purpose of the decorator was to help reduce confusion between the block statement and a for loop. Since you can no longer swallow exceptions, there is no downside to using an existing generator as the target of a do statement. That is, the concern about generators catching StopIteration from a yield doesn't matter, as they will simply step through to their next yield statement, and then the original exception will propagate. The added complexity is caused by the need to separate VAR from EXPR so that a generator can be used. I personally like this separation; I actually like that the anonymous block controller is logically separate from the variable bound by the construct. From Greg Ewing's response to the proposal to endow file objects with __enter__ and __exit__ methods, I believe he thinks so too. Straight up-or-down votes in the full senate are appreciated at this point. +1. On to the secondary questions: - Today I like the 'do' keyword better; 'with' might confuse folks coming from Pascal or VB +1 on do EXPR as VAR, where VAR may be any valid LHS of an assignment. This means that __exit__ can be called with the following arguments: abc.__exit__(True) - normal completion of BLOCK abc.__exit__(False) - BLOCK was left by a non-local goto (break/continue/return) abc.__exit__(False, t, v, tb) - BLOCK was left by an exception (An alternative would be to always call it with 4 arguments, the last three being None in the first two cases.) I'm not sure the extra argument is a good idea; doesn't this introduce the same sort of invisible control flow as swallowing exceptions? Also, since the block controller can't actually change the control flow, I'm having a hard time thinking of any actual use cases for this information. If we adopt PEP 340 redux, it's up to the decorator for degenerate generators to decide how to pass this information into the generator; if we adopt PEP 342 (continue EXPR) at the same time, we can let the yield-expression return a 4-tuple (oke, t, v, tb). Most templates can ignore this information (so they can just use a yield-statement). I was going to propose having a generator-iterator's __exit__() raise the triple inside the generator, or raise StopIteration inside the generator if there is no triple. I'd ideally also like close() as a synonym for __exit__() with no arguments. Although these are properly the subject of PEPs 288 and 325 respectively, I felt this would elegantly bring them both to closure. However, after thinking it through, I realized that I don't see any obvious way to make __exit__ reusable for PEPs 288 and 325, because for 288 at least, I'd want __exit__ to either return the next yielded value or raise StopIteration. But, this isn't compatible with the do protocol's needs, unless the do protocol suppressed StopIteration, and that doesn't seem like such a good idea. It seems to me that passing exceptions into a generator does in fact require a distinct method. But, I still do believe that generator-iterators can have predefined __enter__ and __exit__ methods without the need for a decorator. PS. I've come up with another interesting use case: block signals for the duration of a block. This could be a function in the signal module, e.g. signal.blocking([ist of signals to block]). The list would default to all signals. Similar signal.ignoring(). Sweet. You could also use it for temporary signal handling, i.e. set this signal handler for the duration of the block. Sort of the same class of make sure I restore a global I'm tampering with use case as redirecting stdout, and Tim Peters' Decimal context use cases. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Michael Hudson, after much thinking aloud] Oh, I guess the point is that with a decorated generator you can yield a value to be used as VAR, rather than just discarding the value as here. Hmm. Right. (I thought it was worth quoting this for the benefit of other who went down the same trail but didn't quite make it to this destination.) If things were fiddled such that sys.exc_info() return non-Nones when a finally clause is being executed because of an exception, we don't really need this wart, do we? The problem is that sys.exc_info() almost always returns *something* -- it's usually the last exception that was *ever* caught, except in certain circumstances. Phillip wrote on the same issue: I'm not sure the extra argument is a good idea; doesn't this introduce the same sort of invisible control flow as swallowing exceptions? Also, since the block controller can't actually change the control flow, I'm having a hard time thinking of any actual use cases for this information. The 'oke' argument is so that the author of transactional() can decide what to do with a non-local goto: commit, rollback or hit the author over the head with a big stick. [Michael again] Compare and contrast: @template def redirected_stdout(out): save_stdout = sys.stdout sys.stdout = out yield None sys.stdout = save_stdout class redirected_stdout(object): def __init__(self, output): self.output = output def __enter__(self): self.save_stdout = sys.stdout sys.stdout = self.output def __exit__(self): sys.stdout = self.save_stdout The former is shorter and contains less (well, no) 'self.'s, but I think I find the latter somewhat clearer. Tastes differ. I think the generator wins; more so when there's more state to remember. [Michael quoting Guido] The added complexity is caused by the need to separate VAR from EXPR so that a generator can be used. I personally like this separation; I actually like that the anonymous block controller is logically separate from the variable bound by the construct. Nevertheless, I think I actually like this argument! (Repeated for the benefit of others.) Straight up-or-down votes in the full senate are appreciated at this point. +1 for the PEP 340 variant. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
At 08:41 AM 5/13/2005 -0700, Guido van Rossum wrote: The 'oke' argument is so that the author of transactional() can decide what to do with a non-local goto: commit, rollback or hit the author over the head with a big stick. Since this is just a replacement for a try/except/finally block, I'd expect that in a transactional case that a non-local goto would work the same as any other non-exception exit. ISTM that the resource block use cases are: * Save the current state of something, modify it, and then restore the old state once the block completes (try/finally, used for locking, redirection, signals, decimal context, etc.) * Automatically roll back partially-done work in case of exception, and/or roll forward completed work (try/except/else, used for transaction scenarios) * Release allocated resource(s) after use (try/finally, used to close files and suchlike) None of these, AFAICT, benefit from differing behavior in the presence of nonlinear (but non-exceptional) control flow. It just seems too magical to me in the new context. When we were talking about a block construct or user-defined syntax, it made more sense because you could actually redefine the *meaning* of those constructs to some extent -- and because the *target* of the break and continue statements at least was the block itself, not some containing block. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Tidier Exceptions
[Guido, on string exceptions] ... Last I looked Zope 2 still depended on them (especially in the bowels of ZODB); maybe Tim Peters knows if that's still the case. Certainly none of that in ZODB, or in ZRS. Definitely some in Zope 2.6: http://mail.zope.org/pipermail/zope-tests/2005-May/002110.html I don't think there are any string exceptions in Zope 2.7, Zope 2.8, or Zope 3. Development on Zope 2.6 stopped about a year ago, so the 2.6 story will never change; by the same token, no version of Python after 2.3.5 will ever be approved for use with 2.6 anyway. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
On 5/13/05, Guido van Rossum [EMAIL PROTECTED] wrote: So then the all-important question I want to pose is: do we like the idea of using a (degenerate, decorated) generator as a template for the do-statement enough to accept the slightly increased complexity? +0. I'm not thoroughly convinced that generators are that much easier to read than a class. But I don't find them hard to read, and I think it would only take a little effort to learn that generators might not always be intended to build iterators. If we do support generators in do-statements, I'd like their __enter__() and __exit__() methods (if possible) to have semantics like Nick Coghlan suggested[1], so that: * __enter__() raises an exception if next() has already been called, and * __exit__() raises an exception if StopIteration is not raised The first makes sure that the generator is only used once, and the second makes sure that there is only one yield on the given control path through the generator. In all but the most sick and twisted code, raising exceptions like this will be identifying errors in how the generator was written. Straight up-or-down votes in the full senate are appreciated at this point. +1 on the PEP 340 redux semantics. On to the secondary questions: - Today I like the 'do' keyword better; 'with' might confuse folks coming from Pascal or VB +1 on using 'do'. - I have a more elaborate proposal for __exit__'s arguments. Let the translation be as follows: [snip] abc.__exit__(True) - normal completion of BLOCK abc.__exit__(False) - BLOCK was left by a non-local goto (break/continue/return) abc.__exit__(False, t, v, tb) - BLOCK was left by an exception -1. This looks like a fair bit of added complexity for not much gain. The only example that even *might* make use of this was the transactional one, and I haven't yet seen a use case where it actually *is*. The simpler semantics give you the difference between a normal exit and an exceptional exit. I'd like to see an example that needs to know the difference between block completion exit and a break/continue/return exit before I'd want to make PEP 340 redux this much more complex. STeVe [1] http://members.iinet.net.au/~ncoghlan/public/pep-3XX.html -- You can wordify anything if you just verb it. --- Bucky Katt, Get Fuzzy ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Guido] The 'oke' argument is so that the author of transactional() can decide what to do with a non-local goto: commit, rollback or hit the author over the head with a big stick. [Phillip J. Eby] Since this is just a replacement for a try/except/finally block, I'd expect that in a transactional case that a non-local goto would work the same as any other non-exception exit. ISTM that the resource block use cases are: * Save the current state of something, modify it, and then restore the old state once the block completes (try/finally, used for locking, redirection, signals, decimal context, etc.) * Automatically roll back partially-done work in case of exception, and/or roll forward completed work (try/except/else, used for transaction scenarios) * Release allocated resource(s) after use (try/finally, used to close files and suchlike) None of these, AFAICT, benefit from differing behavior in the presence of nonlinear (but non-exceptional) control flow. It just seems too magical to me in the new context. When we were talking about a block construct or user-defined syntax, it made more sense because you could actually redefine the *meaning* of those constructs to some extent -- and because the *target* of the break and continue statements at least was the block itself, not some containing block. That works for me; I was just hypothesizing about the needs of others, but personally I'm fine with not knowing. I guess part of my motivation is also that this information is readily available intenally when a finally-clause is executed, since when the clause completes a pending non-local goto has to be resumed. But there's no reason to expose *all* internal state information... So the signature of __exit__ is just what sys.exc_info() returns. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Steven Bethard] +0. I'm not thoroughly convinced that generators are that much easier to read than a class. But I don't find them hard to read, and I think it would only take a little effort to learn that generators might not always be intended to build iterators. I am proposing (like Phillip Eby in his response to PEP 340) to use a special decorator that turns a generator into a do-template, so the intention is evident from the generator declaration. If we do support generators in do-statements, I'd like their __enter__() and __exit__() methods (if possible) to have semantics like Nick Coghlan suggested[1], so that: * __enter__() raises an exception if next() has already been called, and * __exit__() raises an exception if StopIteration is not raised I guess you missed my post where I gave the code for the decorator; it does exactly that. The simpler semantics give you the difference between a normal exit and an exceptional exit. I'd like to see an example that needs to know the difference between block completion exit and a break/continue/return exit before I'd want to make PEP 340 redux this much more complex. I agreed to that in my response to Phillip Eby. I do want to pass the exception into __exit__ so that it can be logged, for example. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Guido van Rossum wrote: I just read Raymond Chen's rant against control flow macros: http://blogs.msdn.com/oldnewthing/archive/2005/01/06/347666.aspx I think this pretty much kills PEP 340, as well as Nick Coghlan's alternative: both proposals let you write a template that can be used to hide exception-catching code, which is a form of control flow (and a pretty important one if you read Chen's rant against exceptions referenced by the former, even if you don't agree with everything he says in the latter). It seems the effect of Raymond's articles on you was similar to their effect on me :) Straight up-or-down votes in the full senate are appreciated at this point. PEP 340 redux for me (as you might have guessed) - I think the transaction() use case is a genuinely useful one. The ability to access the return value of __enter__() is also more useful than simply duplicating what could be achieved by an assignment on the line before the user defined statement. On to the secondary questions: - Today I like the 'do' keyword better; 'with' might confuse folks coming from Pascal or VB I think 'do' can be made to read correctly in more contexts that 'with'. The lack of a corresponding 'while' or 'until' should eliminate any temptation to see it as a loop. The 'with' keyword also means I keep wanting the magic methods to be called __acquire__ and __release__ (and those would be harder to type. . .) - I have a more elaborate proposal for __exit__'s arguments. Let the translation be as follows: I plan to rewrite my proposal based on this suggestion, just to explore the ramifications. I think it will turn out quite nicely. The ban on yielding inside try/finally will need to be extended to yielding inside user defined statements until such time as an iterator finalisation protocol is chosen, though. (An alternative would be to always call it with 4 arguments, the last three being None in the first two cases.) The former is probably tidier. __exit__() method implementations which don't care about the exception details can still use *exc_info in the argument signature, while those that want to use the information can just name the three parts without needing to specify the =None defaults. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Michael Hudson wrote: Looking at my above code, no (even though I think I've rendered the point moot...). Compare and contrast: @template def redirected_stdout(out): save_stdout = sys.stdout sys.stdout = out yield None sys.stdout = save_stdout class redirected_stdout(object): def __init__(self, output): self.output = output def __enter__(self): self.save_stdout = sys.stdout sys.stdout = self.output def __exit__(self): sys.stdout = self.save_stdout The former is shorter and contains less (well, no) 'self.'s, but I think I find the latter somewhat clearer. the same argument could be used (and was probably used) against generators: why not just use __getitem__ and instance state? as soon as you write something longer than four lines, using more than one state variable, you'll find that generator-based code is a lot more readable. /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Nick Coghlan] The ban on yielding inside try/finally will need to be extended to yielding inside user defined statements until such time as an iterator finalisation protocol is chosen, though. Ah! Good point. This breaks PEP 340 example 5. No big deal, but worth noting. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Guido van Rossum wrote: PEP 340 redux = Syntax: do EXPR [as VAR]: BLOCK Translation: abc = EXPR [VAR =] abc.__enter__() try: BLOCK finally: abc.__exit__(*sys.exc_info()) # Not exactly Pros: - can use a decorated generator as EXPR - separation of EXPR and VAR (VAR gets what EXPR.__enter__() returns) Cons: - slightly less simple (__enter__ must return something for VAR; __exit__ takes optional args) what happened to the original yield the target object solution? or did I just dream that? /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Phillip J. Eby wrote: At 08:41 AM 5/13/2005 -0700, Guido van Rossum wrote: The 'oke' argument is so that the author of transactional() can decide what to do with a non-local goto: commit, rollback or hit the author over the head with a big stick. snip * Automatically roll back partially-done work in case of exception, and/or roll forward completed work (try/except/else, used for transaction scenarios) Doing transactions with try/except/else is not quite correct, since using any of the three non-local goto's actually executes neither the commit nor the rollback (of course, this is where Guido's stick comment comes into play. . .). However, I'm fine with declaring that, from the perspective of a statement template, 'return', 'break' and 'continue' are all 'non-exceptional exits', and so templates like transaction() are expected to treat them as such. Picking one way and enforcing it by restricting the information seen by __exit__() also seems to be a much better option than allowing the possibility of: do bobs.transaction(): break # Triggers a rollback! do alices.transaction(): break # Triggers a commit! Going the 'non-exceptional exits' route also saves inventing a pseudo-exception to stand in for the 3 non-local goto statements (such a pseudo-exception would recreate the above behavioural hole, anyway). An exceptional exit can be forced if a non-local goto needs to be executed in response to a failure: class AbortDo(Exception): pass do alices.transaction(): break # Triggers a commit (non-exceptional exit) try: do alices.transaction(): raise AbortDo # Triggers a rollback (exceptional exit) except AbortDo: break Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Guido van Rossum] Cons: - slightly less simple (__enter__ must return something for VAR; __exit__ takes optional args) [Fredrik Lundh] what happened to the original yield the target object solution? or did I just dream that? Don't worry, that works when you use a generator. It just doesn't work when you're using a class. The do-statement proposal is a bit ambiguous: on the one hand it's not strongly tied to generators, since you can easily write a class with __enter__ and __exit__ methods; on the other hand its essential difference from PEP 310 is that you *can* use a generator, given a suitable decorator. BTW, we need a name for such a decorated generator that only yields once. I propose to call it a degenerator. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Python's Unicode width default (New Py_UNICODE doc)
M.-A. Lemburg wrote: I'm not breaking anything, I'm just correcting the way things have to be configured in an effort to bring back the cross-platforma configure default. Your proposed change will break the build of Python on Redhat/Fedora systems. I'm talking about the *configure* default, not the default installation you find on any particular platform (this remains a platform decision to be made by the packagers). Why is it good to have such a default? Why is that so good that its better than having Tkinter work by default? The main point is that we can no longer tell users: if you run configure without any further options, you will get a UCS2 build of Python. It's not a matter of telling the users no longer. We currently don't tell that in any documentation; if you had been telling that users, you were wrong. ./configure --help says that the default for --enable-unicode is yes. I want to restore this fact which was true before Jeff's patch was applied. I understand that you want that. I'm opposed. Telling users to look at the configure script printout to determine whether they have just built a UCS2 or UCS4 is just not right given its implications. Right. We should tell them what the procedure is that is used. It will continue to work - the only change, if any, is to add --enable-unicode=tcl or --enable-unicode=ucs4 (if you know that TCL uses UCS4) to your configure setup. The --enable-unicode=ucs4 configure setting is part of RedHat and SuSE already, so there won't be any changes necessary. Yes, but users of these systems need to adjust. Regards, Martin ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Tidier Exceptions
Guido van Rossum wrote: [Brett C.] Seems like, especially if we require inheritance from a base exception class in Python 3000, exceptions should have standard 'arg' and 'traceback' attributes with a possible 'context' attribute (or always a 'context' attribute set to None if not a chained exception). I don't think there is other data normally associated with exceptions is there? I despise the arg argument -- I like Java's message concept better. Works for me. I really need to get off my ass one of these days and just write a PEP targeted for Python 3000 with base inheritance, standard attributes (including exception chains), reworking the built-in exception inheritance hierarchy, and whether bare 'except' statements should go or only catch certain exceptions. Could probably stand to break it up until multiple PEPs, though. =) +1. I think these things are sufficiently closely related to keep them all in one PEP. OK, I will see if I can get to the PEP this summer assuming I have time (waiting on official offer on an internship that will keep me busy this summer, but I am hoping to spend my free time Python hacking; got to finish the AST branch some day =). Probably will also write it up in parts as outlined above so that I can just get parts out quickly without being held up by discussions about other sections. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Chained Exceptions
Guido van Rossum wrote: [Guido] What if that method catches that exception? [Ka-Ping Yee] Did you mean something like this? def handle(): try: open('spamspamspam') except: catchit() # point A ... def catchit(): try: 1/0 except: pass Then there's no exception to propagate, so it doesn't matter. Once we're get to point A, the division by zero is long forgotten. But at what point does the attaching happen? If I catch the ZeroDivisionException inside catchit() and inspects its context attribute, does it reference the IOError instance raised by open('spamspamspam')? Yes, at least in the way I am imagining this being implemented. I was thinking that when an exception happens, the global exception variable is checked to see if it has a value. If it does that gets assigned to the new exception's 'context' attribute and the new exception gets assigned to the global exception variable. This could potentially cause a lot of extra work: when an inner loop that raises and catches lots of exceptions is invoked in the context of having caught an exception at some outer level, the inner loop keeps attaching the outer exception to each exception raised. [this also contains a partial answer to Philip's email also in this thread] Maybe, but as long as caught exceptions get cleared that should be an issue. Would this be solved if, when an 'except' branch is exited, exceptions are cleared? So, in the above example, once the 'pass' is hit in catchit() no exception is considered active any longer. This could be done with a CLEAR_EXC opcode very easily inserted at the end of an 'except' branch by the compiler. This would require explicit re-raising of exceptions to keep them alive after an 'except' ends, but I think that is actually a good idea and since this might all wait until Python 3000 anyway we don't need to worry about the semantic change. -Brett ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Python's Unicode width default (New Py_UNICODE doc)
Martin v. Löwis wrote: M.-A. Lemburg wrote: I'm not breaking anything, I'm just correcting the way things have to be configured in an effort to bring back the cross-platforma configure default. Your proposed change will break the build of Python on Redhat/Fedora systems. You know that this is not true. Python will happily continue to compile on these systems. I'm talking about the *configure* default, not the default installation you find on any particular platform (this remains a platform decision to be made by the packagers). Why is it good to have such a default? Why is that so good that its better than having Tkinter work by default? It is important to be able to rely on a default that is used when no special options are given. The decision to use UCS2 or UCS4 is much too important to be left to a configure script. The main point is that we can no longer tell users: if you run configure without any further options, you will get a UCS2 build of Python. It's not a matter of telling the users no longer. We currently don't tell that in any documentation; if you had been telling that users, you were wrong. ./configure --help says that the default for --enable-unicode is yes. Let's see: http://www.python.org/peps/pep-0100.html http://www.python.org/peps/pep-0261.html http://www.python.org/doc/2.2.3/whatsnew/node8.html Apart from the mention in the What's New document for Python 2.2 and a FAQ entry, the documentation doesn't mention UCS4 at all. However, you're right: the configure script should print (default if ucs2). I want to restore this fact which was true before Jeff's patch was applied. I understand that you want that. I'm opposed. Noted. Telling users to look at the configure script printout to determine whether they have just built a UCS2 or UCS4 is just not right given its implications. Right. We should tell them what the procedure is that is used. No, we should make it an explicit decision by the user running the configure script. BTW, a UCS4 TCL is just as non-standard as a UCS4 Python build. Non-standard build options should never be selected by a configure script all by itself. It will continue to work - the only change, if any, is to add --enable-unicode=tcl or --enable-unicode=ucs4 (if you know that TCL uses UCS4) to your configure setup. The --enable-unicode=ucs4 configure setting is part of RedHat and SuSE already, so there won't be any changes necessary. Yes, but users of these systems need to adjust. Not really: they won't even notice the change in the configure script if they use the system provided Python versions. Or am I missing something ? Regardless of all this discussion, I think we should try to get _tkinter.c to work with a UCS4 TCL version as well. The conversion from UCS4 (Python) to UCS2 (TCL) is already integrated, so adding support for the other way around should be rather straight forward. Any takers ? Regards, -- Marc-Andre Lemburg eGenix.com Professional Python Services directly from the Source (#1, May 13 2005) Python/Zope Consulting and Support ...http://www.egenix.com/ mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/ mxODBC, mxDateTime, mxTextTools ...http://python.egenix.com/ ::: Try mxODBC.Zope.DA for Windows,Linux,Solaris,FreeBSD for free ! ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Guido van Rossum] So then the all-important question I want to pose is: do we like the idea of using a (degenerate, decorated) generator as a template for the do-statement enough to accept the slightly increased complexity? [Greg Ewing] I can't see how this has anything to do with whether a generator is used or not. Keeping them separate seems to be a useful thing in its own right. Assuming by them you mean the value of EXPR and the value assigned to VAR, I don't care how this conclusion is reached, as long as their separation is seen as a useful thing. :-) I came up with the idea of making them separate when I tried to figure out how to decorate a generator to drive a PEP-310-style with-statement, and found I couldn't do it for the opening() example. (Michael Hudson illustrated this nicely in his reply in this thread. :-) But it's fine if the separation is considered generally useful even without thinking of generators. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Here's my vote on things at the moment: +1 on do EXPR as VAR: ... +1 on keeping the EXPR and VAR distinct. +1 on keeping the do and generator protocols distinct. +1 on not going out of our way to let the controller catch exceptions or alter control flow. Let's keep it as simple as we can. -0.7 on directly giving generators do-protocol methods. I'm not yet convinced that encouraging people to use generators to implement block controllers is a good idea. If we blur the distinction too much at this stage, we may regret it later if we come up with a better idea. Also I don't see that people will be writing block controllers anywhere near as often as iterators, so writing classes for them isn't going to be a big chore. And people can always use a do-protocol-to-generator adaptor if they really want. Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
Guido van Rossum wrote: BTW, we need a name for such a decorated generator that only yields once. I propose to call it a degenerator. Cute, but 'template generator' may be clearer (that's what I've been calling them so far, anyway). Then 'iterator generator' can be used to explicitly refer to generators intended for use in for loops. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Merging PEP 310 and PEP 340-redux?
[Greg Ewing] -0.7 on directly giving generators do-protocol methods. I'm -1 on this myself. I'm not yet convinced that encouraging people to use generators to implement block controllers is a good idea. If we blur the distinction too much at this stage, we may regret it later if we come up with a better idea. Also I don't see that people will be writing block controllers anywhere near as often as iterators, so writing classes for them isn't going to be a big chore. And people can always use a do-protocol-to-generator adaptor if they really want. Right. I'm +0 on adding a standard module defining a do_template decorator that turns a degenerate generator into a do-statement controller. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: I've written up the specs for my PEP 340 redux proposal as a separate PEP, PEP 343. http://python.org/peps/pep-0343.html Those who have been following the thread Merging PEP 310 and PEP 340-redux? will recognize my proposal in that thread, which received mostly positive responses there. Please review and ask for clarifications of anything that's unclear. +1 here. The stdout redirection example needs to be corrected to avoid yielding inside a try/finally though: 5. Redirect stdout temporarily: @do_template def redirecting_stdout(new_stdout): save_stdout = sys.stdout try: sys.stdout = new_stdout except: sys.stdout = save_stdout raise else: yield None sys.stdout = save_stdout Used as follows: do opening(filename, w) as f: do redirecting_stdout(f): print Hello world This could be left as the more elegant original if iterator finalisation (e.g. using a __finish__() slot) came in at the same time as user defined statements, allowing the above to be written naturally with try/finally. Arnold deVos's HTML tagging example would need access to the exception information and could be rewritten as a class: def tag(object): def __init__(self, name): self.name = cgi.escape(name) def __enter__(self): print '%s' % self.name return self.name def __exit__(self, *exc_info): if not exc_info or exc_info[0] is None: print '/%s' % self.name Used as follows:: do tag('html'): do tag('head'): do tag('title'): print 'A web page' do tag('body'): for par in pars: do tag('p'): print par Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
[Phillip J. Eby] May I suggest this alternative translation in the Specification section: abc = EXPR __args = () # pseudo-variable, not visible to the user try: VAR = abc.__enter__() try: BLOCK except: __args = sys.exc_info() finally: abc.__exit__(*__args) Done (except you forgot to add a raise to the except claise). While slighly more complex than the current translation, the current translation seems a bit misleading to me. OTOH, that may simply be because I see the *sys.exc_info() part and immediately wonder what happens when there was no exception, and sys.exc_info() contains some arbitrary previous data... Right. Well, anyway, the actual implementation will just get the exception info from the try/finally infrastructure -- it's squirreled away somewhere on the stack even if sys.exc_info() (intentionally) doesn't have access to it. Also, one question: will the do protocol be added to built-in resource types? That is, locks, files, sockets, and so on? One person proposed that and it was shot down by Greg Ewing. I think it's better to require a separate wrapper. Or will there instead be macros like the opening and locking templates? I notice that grammatically, do gerund works a lot better than do noun, so all of your examples are words like locking, blocking, opening, redirecting, and so on. This makes it seem awkward for e.g. do self.__lock, which doesn't make any sense. But the extra call needed to make it do locking(self.__lock) seems sort of gratuitous. Maybe. There seems to be a surge of proponents for 'do' at the moment. It makes me wonder if with or using or some similar word that works better with nouns might be more appropriate, as then it would let us just add the resource protocol to common objects, and still read well. For example, a Decimal Context object might implement __enter__ by setting itself as the thread-local context, and __exit__ by restoring the previous context.do aDecimalContext doesn't make much sense, but with aDecimalContext or using aDecimalContext reads quite nicely. Maybe. I think we ought to implement the basic mechanism first and then decide how fancy we want to get, so I'd rather not get into this in the PEP. I'll add this to the PEP. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
[Nick Coghlan] The stdout redirection example needs to be corrected to avoid yielding inside a try/finally though: Thanks -- fixed now. This could be left as the more elegant original if iterator finalisation (e.g. using a __finish__() slot) came in at the same time as user defined statements, allowing the above to be written naturally with try/finally. Let's not try to tie this to other features. I tried that with PEP 340 and you know the mess it became. :-) -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 343 - Abstract Block Redux
Guido van Rossum wrote: I've written up the specs for my PEP 340 redux proposal as a separate PEP, PEP 343. http://python.org/peps/pep-0343.html Those who have been following the thread Merging PEP 310 and PEP 340-redux? will recognize my proposal in that thread, which received mostly positive responses there. Please review and ask for clarifications of anything that's unclear. There's a typo in the code snippets at the moment. The translation of the above statement is: abc = EXPR exc = () # Or (None, None, None) ? try: try: VAR = abc.__enter__() BLOCK except: exc = sys.exc_info() raise finally: abc.__exit__(exc) I think you meant abc.__exit__(*exc). Assuming that, then exc = (None, None, None) makes the most sense. If exc_info() is going to be passed as a single arg, then I'd rather have the default exc = (), so I can simply check if exc: in the __exit__ method. Robert Brewer System Architect Amor Ministries [EMAIL PROTECTED] ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com