Open ZaxR opened 4 years ago
I suppose your case is a well-known problem of decorators. functools.wraps()
will resolve your case. Please try it.
https://docs.python.org/3/library/functools.html#functools.wraps
Can you elaborate on what you mean? I'm already using wraps for the function, but this is a class factory. Where would I put the functools.wraps in this?
class BaseDecorator(object):
def __init__(self, *args, **kwargs):
...
def __call__(self, f):
@functools.wraps(f)
def decorated(*args, **kwargs):
df = f(*args, **kwargs)
if self.enabled:
self.check_func(df, **self.check_func_params)
return df
return decorated
def decorator_factory(decorator_name, func):
"""Takes in a function and outputs a class that can be used as a decorator."""
class decorator_name(BaseDecorator):
__doc__ = func.__doc__
check_func = staticmethod(func)
return decorator_name
# Automatically creates decorators for each function in bulwark.checks
this_module = sys.modules[__name__]
check_functions = [func[1]
for func in getmembers(ck, isfunction)
if func[1].__module__ == 'bulwark.checks']
for func in check_functions:
decorator_name = snake_to_camel(func.__name__)
setattr(this_module, decorator_name, decorator_factory(decorator_name, func))
To clarify, the setting of doc is working in python:
>>> import bulwark.decorators as dc
>>> dc.HasColumns.__doc__
'Asserts that `df` has ``columns``\n\n Args:\n df (pd.DataFrame): Any pd.DataFrame.\n columns (list or tuple): Columns that are expected to be in ``df``.\n exact_cols (bool): Whether or not ``columns`` need to be the only columns in ``df``.\n exact_order (bool): Whether or not ``columns`` need to be in\n the same order as the columns in ``df``.\n\n Returns:\n Original `df`.\n\n '
Oh, I'm very sorry. I overlooked your last comment. It seems decorator_name
class in the decorator_factory
decorator has its original __name__
. Please check dc.HasColumns.__name__
(or __qualname__
). Indeed, you overrides __doc__
attributes manually. But some other attributes are not.
Please check the document of functools.update_wrapper()
(a function called inside functools.wraps()
). It describes some attributes are copied.
https://docs.python.org/3/library/functools.html#functools.update_wrapper
Describe the bug I have a library module where functions have decorator versions generated for them via a factory function. The newly generated decorators have docstrings inherited from the base function. Factory code below, for context, see https://github.com/ZaxR/bulwark/blob/master/bulwark/decorators.py:
When I check the docstrings via the code, everything looks fine, but my Sphinx docs show each decorator's docstring as:
See https://bulwark.readthedocs.io/en/latest/_source/bulwark.decorators.html#bulwark.decorators.HasColumns .
To Reproduce Steps to reproduce the behavior:
Expected behavior I would like the factory-generated decorators to each show their docstring in the Sphinx docs.
Your project https://github.com/ZaxR/bulwark
Screenshots Example on readthedocs: https://bulwark.readthedocs.io/en/latest/_source/bulwark.decorators.html#bulwark.decorators.
Environment info
Additional context Link above is to the readthedocs, but the same behavior is observed locally as well.