import contextlib
import unittest
class SafeContextMixin:
def __init__ ( self , *args, **kwargs) :
with contextlib.ExitStack ( ) as es:
init = self ._safe_init( *args, **kwargs)
ret = None
while True :
try :
ret = es.enter_context ( init.send ( ret) )
except StopIteration :
break
self .__exit_stack = es.pop_all ( )
def __enter__( self ) :
return self
def __exit__( self , et, ev, eb) :
self .close ( )
def close( self ) :
self .__exit_stack.close ( )
# test
@ contextlib.contextmanager
def good( ) :
print ( "good init" )
try :
yield 42
finally :
print ( "good close" )
@ contextlib.contextmanager
def bad( ) :
print ( "bad init" )
raise Exception ( "bad" )
class Foo( SafeContextMixin) :
def _safe_init( self , m1, m2) :
self .f1 = yield m1( )
self .f2 = yield m2( )
def test ( m1, m2) :
print ( "---" )
try :
print ( "Before with" )
with Foo( m1, m2) as f:
print ( "Inside with" )
print ( "After with" )
except Exception as e:
print ( "Caugth :" , e)
test ( good, good)
test ( good, bad)
test ( bad, bad)
aW1wb3J0IGNvbnRleHRsaWIKaW1wb3J0IHVuaXR0ZXN0CgpjbGFzcyBTYWZlQ29udGV4dE1peGluOgoJZGVmIF9faW5pdF9fKHNlbGYsICphcmdzLCAqKmt3YXJncyk6CgkJd2l0aCBjb250ZXh0bGliLkV4aXRTdGFjaygpIGFzIGVzOgoJCQlpbml0ID0gc2VsZi5fc2FmZV9pbml0KCphcmdzLCAqKmt3YXJncykKCQkJcmV0ID0gTm9uZQoJCQl3aGlsZSBUcnVlOgoJCQkJdHJ5OgoJCQkJCXJldCA9IGVzLmVudGVyX2NvbnRleHQoaW5pdC5zZW5kKHJldCkpCgkJCQlleGNlcHQgU3RvcEl0ZXJhdGlvbjoKCQkJCQlicmVhawoJCQlzZWxmLl9fZXhpdF9zdGFjayA9IGVzLnBvcF9hbGwoKQoJZGVmIF9fZW50ZXJfXyhzZWxmKToKCQlyZXR1cm4gc2VsZgoJZGVmIF9fZXhpdF9fKHNlbGYsIGV0LCBldiwgZWIpOgoJCXNlbGYuY2xvc2UoKQoJZGVmIGNsb3NlKHNlbGYpOgoJCXNlbGYuX19leGl0X3N0YWNrLmNsb3NlKCkKCQkJCQojIHRlc3QKCkBjb250ZXh0bGliLmNvbnRleHRtYW5hZ2VyCmRlZiBnb29kKCk6CglwcmludCgiZ29vZCBpbml0IikKCXRyeToKCQl5aWVsZCA0MgoJZmluYWxseToKCQlwcmludCgiZ29vZCBjbG9zZSIpCgpAY29udGV4dGxpYi5jb250ZXh0bWFuYWdlcgpkZWYgYmFkKCk6CglwcmludCgiYmFkIGluaXQiKQoJcmFpc2UgRXhjZXB0aW9uKCJiYWQiKQoKY2xhc3MgRm9vKFNhZmVDb250ZXh0TWl4aW4pOgoJZGVmIF9zYWZlX2luaXQoc2VsZiwgbTEsIG0yKToKCQlzZWxmLmYxID0geWllbGQgbTEoKQoJCXNlbGYuZjIgPSB5aWVsZCBtMigpCgpkZWYgdGVzdChtMSwgbTIpOgoJcHJpbnQoIi0tLSIpCgl0cnk6CgkJcHJpbnQoIkJlZm9yZSB3aXRoIikKCQl3aXRoIEZvbyhtMSwgbTIpIGFzIGY6CgkJCXByaW50KCJJbnNpZGUgd2l0aCIpCgkJcHJpbnQoIkFmdGVyIHdpdGgiKQoJZXhjZXB0IEV4Y2VwdGlvbiBhcyBlOgoJCXByaW50KCJDYXVndGggOiIsIGUpCgp0ZXN0KGdvb2QsIGdvb2QpCnRlc3QoZ29vZCwgYmFkKQp0ZXN0KGJhZCwgYmFkKQo=