def wrapper(fn: typing.Callable): if not hasattr(fn, '_depth'): fn._depth = 0 @functools.wraps(fn) def _inner(*args, **kwargs): if fn._depth > n: raise RuntimeError("call depth exceed %d" % n) fn._depth += 1 try: return fn(*args, **kwargs) finally: fn._depth -= 1 _inner._fn = fn return _inner