def handle(exception, callback):
def inner(wrapped):
def f(self, *args, **kwargs):
try:
return wrapped(self, *args, **kwargs)
except exception as exc:
callback(self)
self.rollback()
return 'retry' # enum action result retry value
return f
return inner
def print_action(msg, action):
print(msg.format(action=action.__class__.__name__))
class Action:
def run(self):
pass
def rollback(self):
print_action('Rolling back {action}', self)
class A1(Action):
def run(self):
print_action('Running {action}', self)
class A2(A1):
@handle(
RuntimeError,
lambda action: print_action('Handle RuntimeError for action {action}', action)
)
def run(self):
raise RuntimeError()
class A3(A2):
@handle(
ValueError,
lambda action: print_action('Handle ValueError for action {action}', action)
)
@handle(
IndexError,
lambda action: print_action('Handle IndexError for action {action}', action)
)
def run(self):
raise ValueError()
a1 = A1()
a1.run()
a2 = A2()
a2.run()
a3 = A3()
a3.run()
CgpkZWYgaGFuZGxlKGV4Y2VwdGlvbiwgY2FsbGJhY2spOgoJZGVmIGlubmVyKHdyYXBwZWQpOgoJCWRlZiBmKHNlbGYsICphcmdzLCAqKmt3YXJncyk6CgkJCXRyeToKCQkJCXJldHVybiB3cmFwcGVkKHNlbGYsICphcmdzLCAqKmt3YXJncykKCQkJZXhjZXB0IGV4Y2VwdGlvbiBhcyBleGM6CgkJCQljYWxsYmFjayhzZWxmKQoJCQkJc2VsZi5yb2xsYmFjaygpCgkJCQlyZXR1cm4gJ3JldHJ5JyAjIGVudW0gYWN0aW9uIHJlc3VsdCByZXRyeSB2YWx1ZQoJCXJldHVybiBmCglyZXR1cm4gaW5uZXIKCgpkZWYgcHJpbnRfYWN0aW9uKG1zZywgYWN0aW9uKToKCXByaW50KG1zZy5mb3JtYXQoYWN0aW9uPWFjdGlvbi5fX2NsYXNzX18uX19uYW1lX18pKQoKCmNsYXNzIEFjdGlvbjoKCQoJZGVmIHJ1bihzZWxmKToKCQlwYXNzCgkKCWRlZiByb2xsYmFjayhzZWxmKToKCQlwcmludF9hY3Rpb24oJ1JvbGxpbmcgYmFjayB7YWN0aW9ufScsIHNlbGYpCgoKY2xhc3MgQTEoQWN0aW9uKToKCQoJZGVmIHJ1bihzZWxmKToKCQlwcmludF9hY3Rpb24oJ1J1bm5pbmcge2FjdGlvbn0nLCBzZWxmKQoKCmNsYXNzIEEyKEExKToKCQoJQGhhbmRsZSgKCQlSdW50aW1lRXJyb3IsCgkJbGFtYmRhIGFjdGlvbjogcHJpbnRfYWN0aW9uKCdIYW5kbGUgUnVudGltZUVycm9yIGZvciBhY3Rpb24ge2FjdGlvbn0nLCBhY3Rpb24pCgkpCglkZWYgcnVuKHNlbGYpOgoJCXJhaXNlIFJ1bnRpbWVFcnJvcigpCgpjbGFzcyBBMyhBMik6CgkKCUBoYW5kbGUoCgkJVmFsdWVFcnJvciwKCQlsYW1iZGEgYWN0aW9uOiBwcmludF9hY3Rpb24oJ0hhbmRsZSBWYWx1ZUVycm9yIGZvciBhY3Rpb24ge2FjdGlvbn0nLCBhY3Rpb24pCgkpCglAaGFuZGxlKAoJCUluZGV4RXJyb3IsCgkJbGFtYmRhIGFjdGlvbjogcHJpbnRfYWN0aW9uKCdIYW5kbGUgSW5kZXhFcnJvciBmb3IgYWN0aW9uIHthY3Rpb259JywgYWN0aW9uKQoJKQoJZGVmIHJ1bihzZWxmKToKCQlyYWlzZSBWYWx1ZUVycm9yKCkKCgphMSA9IEExKCkKYTEucnVuKCkKCmEyID0gQTIoKQphMi5ydW4oKQoKYTMgPSBBMygpCmEzLnJ1bigpCgo=