def event_source(method: t.Callable, name: t.Optional[str] = None): """A decorator which makes the function act as a source of before and after call events. You can later subscribe to these event with :py:func:`before` and :py:func`after` decorators. :param method: Target class method :param: Name of for the join point. If not given use the function name. """ # We must use function name instead of function pointer for the registry, because function object changes with unbound vs. bound Python class methods if not name: name = method.__name__ @functools.wraps(method) def _inner(*args, **kwargs): _self = args[0] fire_advisor_event(_self, name, AdvisorRole.before) retval = method(*args, **kwargs) fire_advisor_event(_self, name, AdvisorRole.after) return retval assert name not in _event_source_hooks, "There already exist event_source with same name" _event_source_hooks.append(name) method._event_source_name = name return _inner