from functools import reduce class HookException(Exception): pass class HookMan: hooks = {} def __new__(cls): return reduce(lambda x, y: y(x), cls.hooks, super(HookMan, cls).__new__(cls)) def execute_hooks(self, hook_type, isAdminAction=False, *args, **kwargs): if hook_type not in self.hooks: hook_type = None if isAdminAction: admin_hooks = self.hooks["admin*"] else: admin_hooks = [] for hook in \ (lambda: self.hooks[hook_type] if hook_type in self.hooks else [])() \ + (lambda: self.hooks["*"] if "*" in self.hooks else [])() \ + admin_hooks: print(f"\tExecuting hook {hook.__name__}") try: hook()(hook_type=hook_type, isAdminAction=isAdminAction, *args, **kwargs) except Exception as exc: raise HookException(exc) @classmethod def add_hook(cls, func, *args, **kwargs): """Adds a hook.""" hook_types = func.hook_type for hook_type in hook_types: if hook_type in cls.hooks: cls.hooks[hook_type] = cls.hooks[hook_type] + [func] else: cls.hooks[hook_type] = [func] hook = HookMan()