Nick Coghlan wrote: > Rough spec for the concept: > > Implementing __enter__/__exit__ on a CM would work as per PEP 343. > > Implementing __with__ instead would give the CM complete control over > whether or not to execute the block. > > The implementation of contextlib.GeneratorContextManager would then > change so that instead of providing __enter__/__exit__ as it does now it > would instead provide __with__ as follows:
Expansion in the previous message wasn't quite right since it didn't give the executed block access to the result of __enter__(). Mark II: def __with__(self, exec_block): try: enter_result = self.gen.next() except StopIteration: pass else: try: exec_block(enter_result) except: exc_type, value, traceback = sys.exc_info() try: self.gen.throw(type, value, traceback) raise RuntimeError("generator didn't stop after throw()") except StopIteration, exc: # Suppress the exception *unless* it's the same exception that # was passed to throw(). This prevents a StopIteration # raised inside the "with" statement from being suppressed return exc is not value except: # only re-raise if it's *not* the exception that was # passed to throw(), because __exit__() must not raise # an exception unless __exit__() itself failed. But throw() # has to raise the exception to signal propagation, so this # fixes the impedance mismatch between the throw() protocol # and the __exit__() protocol. if sys.exc_info()[1] is not value: raise else: try: self.gen.next() except StopIteration: return else: raise RuntimeError("generator didn't stop") -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia --------------------------------------------------------------- _______________________________________________ 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