Note: I know that decorators with optional argument contain three nested function. But optional argument here is function itself. Please go through the complete post before you mark this as duplicate. I already tried all the tricks for decorators with optional argument, but I could not found any that takes function as argument.
I am having a decorator for wrapping error:
def wrap_error(func):
from functools import wraps
@wraps(func)
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
import sys
exc_msg = traceback.format_exception(*sys.exc_info())
raise MyCustomError(exc_msg)
return wrapper
If some function raises any exception, it wraps the error. This wrapper is used like:
@wrap_error
def foo():
...
Now I want to modify this wrapper with additional callback function which will be optional. And I want this wrapper to be used as:
@wrap_error
def foo():
...
@wrap_error(callback)
def foo():
...
I know how to write decorators with optional arguments (in case passed argument is not function, based on isfunction(func)
check within wrapper). But I am not sure how to handle this case.
Note: I can not use @wrap_error()
instead of @wrap_error
. This wrapper is used in multiple number of packages, and it is not possible to update the change in all
Here is the blocker: Consider the wrapper as:
@wrap_error(callback) ---> foo = wrap_error(callback)(foo)
def foo():
...
So, by the time wrap_error(foo)
is executed, we do not know whether there will be any callback function for execution after that or not (in case we use just @wrap_error
instead of @wrap_error(callback)
).
If there is no (callback)
, wrapping function within wrap_error will return func(*args. **kwargs)
so that I can raise exception. Else we have to return func
so that it is called at next step, and if func()
raises the exception, we call callback()
in except
block.