[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

Reply via email to