[Alex] > I like this. The only aspect of other proposals that I would sorely > miss here, would be the inability for abc.__exit__ to deal with > exceptions raised in BLOCK (or, even better, a separate specialmethod > on abc called in lieu of __exit__ upon exceptions). Or am I missing > something, and would this give a way within abc.__exit__ to examine > and possibly ``unraise'' such an exception...?
See my followup to Nick. I'm not worried about unraising exceptions. The only way to mess with the exception from code in a finally-suite is to raise another exception, and we can't really prevent that. However (I forgot this in the response to Nick) unless/until we augment generators in some way the generator can't easily see the exception flag. [me] > > can write a relatively straightforward decorator, call it > > @with_template, that endows a generator with the __enter__ and > > __exit__ methods, so you can write all the examples (except > > auto_retry(), which was there mostly to make a point) from PEP 340 > > like this: > > > > @with_template > > def opening(filename, mode="r"): > > f = open(filename, mode) > > yield f > > f.close() > > > > and so on. (Note the absence of a try/finally block in the generator > > -- the try/finally is guaranteed by the with-statement but not by the > > generator framework.) [Alex] > I must be thick this morning, because this relatively straightforward > decorator isn't immediately obvious to me -- care to show me how > with_template gets coded? Here's a sketch: class Wrapper(object): def __init__(self, gen): self.gen = gen self.state = "initial" def __enter__(self): assert self.state == "initial" self.state = "entered" try: return self.gen.next() except StopIteration: self.state = "error" raise RuntimeError("template generator didn't yield") def __exit__(self): assert self.state == "entered" self.state = "exited" try: self.gen.next() except StopIteration: return else: self.state = "error" raise RuntimeError("template generator didn't stop") def with_template(func): def helper(*args, **kwds): return Wrapper(func(*args, **kwds)) return helper @with_template def opening(filename, mode="r"): f = open(filename) # Note that IOError here is untouched by Wrapper yield f f.close() # Ditto for errors here (however unlikely) -- --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