Re: [Python-Dev] PEP 343 rewrite complete
Paul Moore wrote: Unfortunately, I don't have a better naming suggestion (other than simply template, which is probably too general to work), so I just raise this as something you should expect to need to clarify a few times... PEP 346 used statement_template for the generator decorator. That could be shortened to stmt_template without losing much in readability (stmt being a fairly common abbreviation of statement). Avoiding the problem with the English meaning of the phrases do template and with template was part of the reason for PEP 346's choice of name (the other part being that the name tied in nicely with that PEP's user defined statement terminology). 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 rewrite complete
On 6/1/05, Guido van Rossum [EMAIL PROTECTED] wrote: I hope that I've got the rewrite of PEP 343 to include generator extensions right now. I've chosen the 'with' keyword. Please review here; I think this is ready for review by the unwashed masses. :-) http://www.python.org/peps/pep-0343.html A fairly minor point - with_template read wrongly to me for quite a while: I read it as something along the lines of with a template (which then doesn't make much sense...) rather than template for the with statement. Unfortunately, I don't have a better naming suggestion (other than simply template, which is probably too general to work), so I just raise this as something you should expect to need to clarify a few times... Paul. ___ 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 rewrite complete
Guido van Rossum wrote: @with_template def closing(obj): try: yield obj finally: obj.close() I just realized this has a race condition. The bytecode for the expression closing(open(...)) must necessarily contain a bytecode that calls open() followed by another bytecode that calls closing(). This is not a convincing point. That race condition always existed, e.g. in the traditional f = open(filename) try: process(f) finally: f.close() as you could always get an async exception between open returns and f is assigned. This isn't much of an issue, since CPython would always release the file immediately as the stack frame is cleared due to the exception. I think would should explicitly weaken our guarantees for asynchronous exceptions (of which we currently only have KeyboardInterrupt). The PEP should point out that an async exception between the beginning of the with statement and the assignment to the variable may or may not cause __exit__ to be called (depending on how far you are into __enter__) 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] PEP 343 rewrite complete
On 6/5/05, Martin v. Löwis [EMAIL PROTECTED] wrote: Guido van Rossum wrote: @with_template def closing(obj): try: yield obj finally: obj.close() I just realized this has a race condition. The bytecode for the expression closing(open(...)) must necessarily contain a bytecode that calls open() followed by another bytecode that calls closing(). This is not a convincing point. That race condition always existed, e.g. in the traditional f = open(filename) try: process(f) finally: f.close() as you could always get an async exception between open returns and f is assigned. This isn't much of an issue, since CPython would always release the file immediately as the stack frame is cleared due to the exception. I think would should explicitly weaken our guarantees for asynchronous exceptions (of which we currently only have KeyboardInterrupt). The PEP should point out that an async exception between the beginning of the with statement and the assignment to the variable may or may not cause __exit__ to be called (depending on how far you are into __enter__) That is pretty clear from the translation given in the PEP. What is not so clear is that the cace can be completely avoided *if* the call to __enter__ and the try-finally setup are combined in one opcode, *and* __enter__ is implemented in C, *and* the reversible actions are all done by __enter__. This is also why I don't like giving file objects __enter__ and __exit__ methods. I know all this doesn't matter in most situations, but sometimes it does, and it would be good if there was a solution -- today, there really isn't one except to rely on CPython's reference counting. -- --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 rewrite complete
Guido van Rossum wrote: [Phillip J. Eby] * The transaction handler could also be written as: @with_template def transactional(db): db.begin() try: yield db except: db.rollback() else: db.commit() at least, if I understand it correctly. Ah, of course. I've updated the PEP. This template eats eats the exception, which will cause a RuntimeError in the proposed Wrapper, I think. A raise after rollback is needed. - Arnold ___ 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 rewrite complete
Arnold deVos wrote: This template eats eats the exception, which will cause a RuntimeError in the proposed Wrapper, I think. A raise after rollback is needed. Actually, the Wrapper as written in the PEP does not raise RuntimeError if the generator catches a block's exception. Shouldn't the relevant clause in the Wrapper go like this: try: self.gen.throw(type, value, traceback) except type: return except StopIteration: raise RuntimeError(generator caught exception) else: raise RuntimeError(generator didn't stop) And the transaction template would go like this (re-raising the exception): @with_template def transactional(db): db.begin() try: yield None except: db.rollback() raise else: db.commit() At least this is what I gleaned from the earlier threads. It means that the template does not appear to supress an exception that it cannot actually supress. - Arnold ___ 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 rewrite complete
[Arnold deVos, responding to himself] This template eats eats the exception, which will cause a RuntimeError in the proposed Wrapper, I think. A raise after rollback is needed. No, the generator returns after rolling back, which causes throw() to raise StopIteration, which is good enough for the wrapper as written. Actually, the Wrapper as written in the PEP does not raise RuntimeError if the generator catches a block's exception. Shouldn't the relevant clause in the Wrapper go like this: try: self.gen.throw(type, value, traceback) except type: return except StopIteration: raise RuntimeError(generator caught exception) else: raise RuntimeError(generator didn't stop) I considered that, but decided that it should be okay for the generator to respond to a throw() by returning (thus replacing the exception thrown by StopIteration) since the call to __exit__() is contained inside a finally-clause, so that when __exit__() returns normally, the finally-clause will re-raise the original exception anyway. Note that there are currently no other use cases for throw() except the with_template decorator and the close() method. Both allow the generator to respond either by letting the exception pass through it unchanged (after executing finally-clauses if present) or by simply returning (which will raise StopIteration in the caller of throw()). Erroneous behaviors are, in both cases, raising some other exception or *yielding* another value. There may be *other* use cases for yielding a value, for example, a future (looping) block-statement a la PEP 343. Raising another exception is always an indication of a bug in the generator. And the transaction template would go like this (re-raising the exception): @with_template def transactional(db): db.begin() try: yield None except: db.rollback() raise else: db.commit() At least this is what I gleaned from the earlier threads. It means that the template does not appear to supress an exception that it cannot actually supress. I disagree (at the -0 to -0.5 level); given that the with_template decorator allows StopIteration, I think that appearing to suppress an exception it doesn't actually suppress is a minor sin -- the key point is that the cleanup gets executed and doesn't raise a new exception or reaches a yield-statement. I'll summarize this discussion in 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 rewrite complete
[me] I'll summarize this discussion in the PEP. I've added this section to the PEP. Is anyone dead set against the tentative resolutions here? Open Issues Discussion on python-dev has revealed some open issues. I list them here, with my preferred resolution and its motivation. The PEP as currently written reflects this preferred resolution. 1. What exception should be raised by close() when the generator yields another value as a response to the GeneratorExit exception? I originally chose TypeError because it represents gross misbehavior of the generator function, which should be fixed by changing the code. But the with_template decorator class uses RuntimeError for similar offenses. Arguably they should all use the same exception. I'd rather not introduce a new exception class just for this purpose, since it's not an exception that I want people to catch: I want it to turn into a traceback which is seen by the programmer who then fixes the code. So now I believe they should both raise RuntimeError. There are some precedents for that: it's raised by the core Python code in situations where endless recursion is detected, and for uninitialized objects (and for a variety of miscellaneous conditions). 2. Both the generator close() method and the __exit__() method of the with_template decorator class catch StopIteration and consider it equivalent to re-raising the exception passed to throw(). Is allowing StopIteration right here? This is so that a generator doing cleanup depending on the exception thrown (like the transactional() example below) can *catch* the exception thrown if it wants to and doesn't have to worry about re-raising it. I find this more convenient for the generator writer. Against this was brought in that the generator *appears* to suppress an exception that it cannot suppress: the transactional() example would be more clear according to this view if it re-raised the original exception after the call to db.rollback(). I personally would find the requirement to re-raise the exception an annoyance in a generator used as a with-template, since all the code after yield is used for is cleanup, and it is invoked from a finally-clause (the one implicit in the with-statement) which re-raises the original exception anyway. -- --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 rewrite complete
Guido van Rossum wrote: I hope that I've got the rewrite of PEP 343 to include generator extensions right now. I've chosen the 'with' keyword. Please review here; I think this is ready for review by the unwashed masses. :-) http://www.python.org/peps/pep-0343.html Looks pretty good to me (looking at version 1.19). One comment is that, in the 'optional extensions' section, where you say 'such mistakes are easily diagnosed', you could point to your generator wrapper as an example where attempting to reuse the block handler raises a RuntimeError on the second attempt. Also, I'm wondering if it would be useful to have a 'closing' template that looked like: @with_template def closing(obj): try: yield obj finally: obj.close() That can be used to deterministically close anything with a close method, be it file, generator, or something else: with closing(open(argument.txt)) as contradiction: for line in contradiction: print line with closing(some_gen()) as data: for datum in data: process(datum) 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 rewrite complete
At 01:08 AM 6/3/2005 +1000, Nick Coghlan wrote: Also, I'm wondering if it would be useful to have a 'closing' template that looked like: @with_template def closing(obj): try: yield obj finally: obj.close() +1 if you make it 'if hasattr(obj,close): obj.close()' in the finally clause, so that it will still work if the type of the object changes. ___ 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 rewrite complete
On 6/2/05, Phillip J. Eby [EMAIL PROTECTED] wrote: At 01:08 AM 6/3/2005 +1000, Nick Coghlan wrote: Also, I'm wondering if it would be useful to have a 'closing' template that looked like: @with_template def closing(obj): try: yield obj finally: obj.close() +1 if you make it 'if hasattr(obj,close): obj.close()' in the finally clause, so that it will still work if the type of the object changes. But then you'd get back the bug where it would silently do nothing when you pass it the wrong thing; wasn't that argument used against an earlier proposal to skip calling __exit__() when it doesn't exist? -- --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 rewrite complete
At 09:20 AM 6/2/2005 -0700, Guido van Rossum wrote: On 6/2/05, Phillip J. Eby [EMAIL PROTECTED] wrote: At 01:08 AM 6/3/2005 +1000, Nick Coghlan wrote: Also, I'm wondering if it would be useful to have a 'closing' template that looked like: @with_template def closing(obj): try: yield obj finally: obj.close() +1 if you make it 'if hasattr(obj,close): obj.close()' in the finally clause, so that it will still work if the type of the object changes. But then you'd get back the bug where it would silently do nothing when you pass it the wrong thing; That's not a bug, it's a feature. If the object doesn't have a 'close()' method, clearly it doesn't need to be closed. If it's the wrong object for what you're using it for in the body of the 'with' block, it'll show up there, so this doesn't hide any errors. The idea is that with closing(foo): is just an assertion that you only intend to use 'foo' in the body of that block, and not afterwards, so if 'foo' is something that needs closing, go ahead and close it. The specific use case I have in mind is situations where a piece of code expects an iterable, but there are callers (or callees) that need to do cleanup. On the other hand some callers (or callees) would like to just pass in or return a list, or are passing or returning an object from somewhere else that may or may not have a close() method. Thus, a whole bunch of code would suddenly be strewed with assumptions about whether things can be closed or not, which seems like pure administrivia. The important functionality is what the object does *before* you close it; that's what the programmer should be able to remain focused on. wasn't that argument used against an earlier proposal to skip calling __exit__() when it doesn't exist? I thought the resolution of that discussion was that you should use an explicit wrapper if you want this behavior -- which is what 'closing()' is. Anyway, if you don't like it, don't put it in. I just thought it would be a good example to include for a wrapper whose behavior is more optional in nature. ___ 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 rewrite complete
Phillip J. Eby wrote: At 10:00 PM 6/1/2005 +0200, Eric Nieuwland wrote: Phillip J. Eby wrote: -1, too confusing. A matter of taste, I guess. IMHO 'with' secretly handling exceptions is confusing. It doesn't secretly handle them; it simply gets access to them, which is an entirely different thing. By confusing, I mean that it is not clear from your construct what exceptions are caught by the 'except' clause, due to its structural layout. It's also not clear whether the __enter__/__exit__ of EXPR wrap BLOCK1 only, or both BLOCK1 and BLOCK2. These aspects are confusing because whatever decision you make about the semantics, someone will have to *remember* them, as opposed to being unambiguously represented by the block structure. By contrast, if you remove the except: clause from your construct, it is clear that BLOCK1 is what is wrapped, and there is no possible confusion about who sees what exceptions. Exceptions inside the block are communicated to __exit__, exceptions outside (including those in the 'with' statement itself) are not. OK. This forwarding (is that the proper expression here?) of an exception to __exit__ is what I meant by 'secretly handling'. If everybody agrees I'll write with EXPR as VAR: try: BLOCK1 except EXCEPTION: BLOCK2 instead. Seems a waiste to me, though. I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles uncaught exceptions by forwarding it to EXPR's __exit__ method. No confusion with me. --eric ___ 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 rewrite complete
At 10:04 PM 6/2/2005 +0200, Eric Nieuwland wrote: I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles uncaught exceptions by forwarding it to EXPR's __exit__ method. No confusion with me. No doubt. However, it's not obvious what happens to an exception in EXPR; surely it can't be passed to EXPR's __exit__ method. So, is it handled by the try, or does it pass out of the block? Whichever answer you give, there is somebody who will think the opposite. And this is precisely the ambiguity I've been talking about. In contrast, a 'with' unmixed with 'try' is absolutely unambiguous as to which except: clauses handle what exceptions where. ___ 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 rewrite complete
On 2 jun 2005, at 22:12, Phillip J. Eby wrote: At 10:04 PM 6/2/2005 +0200, Eric Nieuwland wrote: I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles uncaught exceptions by forwarding it to EXPR's __exit__ method. No confusion with me. No doubt. However, it's not obvious what happens to an exception in EXPR; surely it can't be passed to EXPR's __exit__ method. So, is it handled by the try, or does it pass out of the block? Whichever answer you give, there is somebody who will think the opposite. And this is precisely the ambiguity I've been talking about. In contrast, a 'with' unmixed with 'try' is absolutely unambiguous as to which except: clauses handle what exceptions where. slap forehead I never thought of that! Now I see what you mean. I could only save my idea by stating the scope of 'try' only starts after the ':', but that seems too artificial. --eric ___ 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 rewrite complete
At 10:16 PM 6/2/2005 +0200, Eric Nieuwland wrote: On 2 jun 2005, at 22:12, Phillip J. Eby wrote: At 10:04 PM 6/2/2005 +0200, Eric Nieuwland wrote: I was thinking about 'try EXPR [as VAR]:' as a 'try' that handles uncaught exceptions by forwarding it to EXPR's __exit__ method. No confusion with me. No doubt. However, it's not obvious what happens to an exception in EXPR; surely it can't be passed to EXPR's __exit__ method. So, is it handled by the try, or does it pass out of the block? Whichever answer you give, there is somebody who will think the opposite. And this is precisely the ambiguity I've been talking about. In contrast, a 'with' unmixed with 'try' is absolutely unambiguous as to which except: clauses handle what exceptions where. slap forehead I never thought of that! Now I see what you mean. I could only save my idea by stating the scope of 'try' only starts after the ':', but that seems too artificial. That's what I mean: if you have to solve it by decree, it becomes a rule that people have to *remember* (or at least read carefully and think about it), which goes against the executable pseudocode nature. ___ 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 rewrite complete
Phillip J. Eby wrote: That's not a bug, it's a feature. If the object doesn't have a 'close()' method, clearly it doesn't need to be closed. If it's the wrong object for what you're using it for in the body of the 'with' block, it'll show up there, so this doesn't hide any errors. For those semantics, I think one of the following would be better: with local(obj): with scoped(obj): but those semantics apply better to __enter__ and __exit__ anyway. I think a closing adaptor should only work with objects that have a close() method. Perhaps: with scoped_closable(obj): Tim Delaney ___ 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 rewrite complete
[Nick Coghlan] Also, I'm wondering if it would be useful to have a 'closing' template that looked like: @with_template def closing(obj): try: yield obj finally: obj.close() That can be used to deterministically close anything with a close method, be it file, generator, or something else: with closing(open(argument.txt)) as contradiction: for line in contradiction: print line with closing(some_gen()) as data: for datum in data: process(datum) I just realized this has a race condition. The bytecode for the expression closing(open(...)) must necessarily contain a bytecode that calls open() followed by another bytecode that calls closing(). If a ^C happens between these two byte codes, the stack contains an open file object that won't be closed explicitly. With the original opening() template, this race can be avoided (and I intend to do so) by implementing opening() in C (as a class with __enter__ and __exit__ methods), and by making sure that the interpreter does *not* check for interrupts between the call to __enter__ and the start of the try-finally-statement in the translation of the with-statement. The only way to avoid the race that I can see with the closing() template would be to disable signals for the duration of the evaluation of the expression in the with-statement, but I really don't like that solution at all -- system calls like that can be excruciatingly expensive compared to bytecode execution. Most applications don't catch ^C so they don't need this extra protection -- but the compiler doesn't know that so everybody pays for it. The solution for avoiding interrupts between the __enter__() call and the try start doesn't require disabling signals; there can be a single opcode that calls __enter__ and sets up the try-finally context. -- --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 rewrite complete
Guido van Rossum wrote: [...] a generator doing cleanup depending on the exception thrown (like the transactional() example below) can *catch* the exception thrown if it wants to and doesn't have to worry about re-raising it. I find this more convenient for the generator writer. Against this was brought in that the generator *appears* to suppress an exception that it cannot suppress: the transactional() example would be more clear according to this view if it re-raised the original exception after the call to db.rollback(). [...] Of course, the explicit re-raise is only needed in a minority of use cases where the exception is caught. Two additional points in favour of this: - refactoring a naked try as a with + template is more direct and uniform across all use cases. - it is upwards compatible if the prohibition on templates suppressing exceptions is ever reconsidered. (Flow control macro discussion not withstanding.) - Arnold ___ 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 rewrite complete
http://www.python.org/peps/pep-0343.html I should add that IMO this obsoletes PEP 288 and PEP 325; I plan to reject those when PEP 343 is accepted. I've already withdrawn PEP 340. PEP 342 is separate (but I'll probably present it together with PEP 343). -- --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 rewrite complete
At 08:16 AM 6/1/2005 -0700, Guido van Rossum wrote: I hope that I've got the rewrite of PEP 343 to include generator extensions right now. I've chosen the 'with' keyword. Please review here; I think this is ready for review by the unwashed masses. :-) http://www.python.org/peps/pep-0343.html Looks great. A few questions/comments: * What's the rationale for raising TypeError from close()? Wasn't RuntimeError discussed previously for that role? (and it's also used by the with_template example) OTOH, maybe that means we want a ControlFlowError or some such that can be used for both. * The opening example under Generator Decorator seems to be missing a try/finally block. * The transaction handler could also be written as: @with_template def transactional(db): db.begin() try: yield db except: db.rollback() else: db.commit() at least, if I understand it correctly. ___ 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 rewrite complete
[Guido van Rossum] http://www.python.org/peps/pep-0343.html [Phillip J. Eby] Looks great. A few questions/comments: * What's the rationale for raising TypeError from close()? Wasn't RuntimeError discussed previously for that role? (and it's also used by the with_template example) OTOH, maybe that means we want a ControlFlowError or some such that can be used for both. I really don't want a new exception for this, since it's just a bug in the generator's code. I could go with RuntimeError here too, but I figured TypeError's meaning in a wider sense applies: the generator doesn't respond appropriately to the throw() call, which is similar to not handling a particular argument (list) correctly. * The opening example under Generator Decorator seems to be missing a try/finally block. Good catch. I've fixed this in the PEP. * The transaction handler could also be written as: @with_template def transactional(db): db.begin() try: yield db except: db.rollback() else: db.commit() at least, if I understand it correctly. Ah, of course. I've updated 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 rewrite complete
Nice going! But ... Could we extend the 'try' syntax for this instead of introducing 'with'? If I look at the translation it an augmented 'try'. with EXPR as VAR: BLOCK1 except EXCEPTION: BLOCK2 could then be translated to abc = EXPR exc = (None, None, None) VAR = abc.__enter__() try: try: BLOCK1 except EXCEPTION: BLOCK2 except: exc = sys.exc_info() raise finally: abc.__exit__(*exc) Can the 'throw()' method be renamed 'raise()'? IMHO that makes much clearer what happens. Same thing with 'GeneratorExit', 'StopGeneration' more closely matches 'StopIteration'. --eric ___ 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 rewrite complete
Eric Nieuwland wrote: If I look at the translation it an augmented 'try'. with EXPR as VAR: BLOCK1 except EXCEPTION: BLOCK2 Oops, that should read: try EXPR as VAR: BLOCK1 except EXCEPTION: BLOCK2 --eric ___ 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 rewrite complete
At 08:46 PM 6/1/2005 +0200, Eric Nieuwland wrote: Nice going! But ... Could we extend the 'try' syntax for this instead of introducing 'with'? If I look at the translation it an augmented 'try'. with EXPR as VAR: BLOCK1 except EXCEPTION: BLOCK2 could then be translated to -1, too confusing. Can the 'throw()' method be renamed 'raise()'? IMHO that makes much clearer what happens. No, 'raise' is a reserved word. It would have to be 'raise_()'. -0. Same thing with 'GeneratorExit', 'StopGeneration' more closely matches 'StopIteration'. StopIteration is raised the *other* way, so closely matching isn't really a benefit. -1. ___ 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 rewrite complete
Phillip J. Eby wrote: At 08:46 PM 6/1/2005 +0200, Eric Nieuwland wrote: If I look at the translation it an augmented 'try'. with EXPR as VAR: BLOCK1 except EXCEPTION: BLOCK2 could then be translated to -1, too confusing. A matter of taste, I guess. IMHO 'with' secretly handling exceptions is confusing. Can the 'throw()' method be renamed 'raise()'? IMHO that makes much clearer what happens. No, 'raise' is a reserved word. It would have to be 'raise_()'. -0. My bad. Should have thought about that. Same thing with 'GeneratorExit', 'StopGeneration' more closely matches 'StopIteration'. StopIteration is raised the *other* way, so closely matching isn't really a benefit. -1. Yep! Misread that one. --eric ___ 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 rewrite complete
At 10:00 PM 6/1/2005 +0200, Eric Nieuwland wrote: Phillip J. Eby wrote: At 08:46 PM 6/1/2005 +0200, Eric Nieuwland wrote: If I look at the translation it an augmented 'try'. with EXPR as VAR: BLOCK1 except EXCEPTION: BLOCK2 could then be translated to -1, too confusing. A matter of taste, I guess. IMHO 'with' secretly handling exceptions is confusing. It doesn't secretly handle them; it simply gets access to them, which is an entirely different thing. By confusing, I mean that it is not clear from your construct what exceptions are caught by the 'except' clause, due to its structural layout. It's also not clear whether the __enter__/__exit__ of EXPR wrap BLOCK1 only, or both BLOCK1 and BLOCK2. These aspects are confusing because whatever decision you make about the semantics, someone will have to *remember* them, as opposed to being unambiguously represented by the block structure. By contrast, if you remove the except: clause from your construct, it is clear that BLOCK1 is what is wrapped, and there is no possible confusion about who sees what exceptions. Exceptions inside the block are communicated to __exit__, exceptions outside (including those in the 'with' statement itself) are not. ___ 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