| 60 | def decorator(func): |
| 61 | @functools.wraps(func) |
| 62 | def wrapper(self, *args, **kwargs): |
| 63 | if not hasattr(self, "hooks") or not isinstance(self.hooks, HookManager): |
| 64 | raise AttributeError( |
| 65 | f"{type(self).__name__} must have a 'hooks' attribute of type HookManager." |
| 66 | ) |
| 67 | self.hooks.dispatch(stage_obj.BEFORE, self, *args, **kwargs) |
| 68 | try: |
| 69 | result = func(self, *args, **kwargs) |
| 70 | except Exception as err: |
| 71 | self.hooks.dispatch(stage_obj.ERROR, self, err, *args, **kwargs) |
| 72 | raise |
| 73 | self.hooks.dispatch(stage_obj.AFTER, self, result, *args, **kwargs) |
| 74 | return result |
| 75 | |
| 76 | return wrapper |
| 77 | |