Skip to content

DOC: Make doc decorator a class and replace Appender by doc #33160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 22, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions pandas/tseries/offsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
shift_month,
)
from pandas.errors import AbstractMethodError
from pandas.util._decorators import Appender, Substitution, cache_readonly
from pandas.util._decorators import cache_readonly, doc

from pandas.core.dtypes.inference import is_list_like

Expand Down Expand Up @@ -1188,11 +1188,12 @@ class BusinessMonthBegin(MonthOffset):
_day_opt = "business_start"


@doc(bound="bound")
class _CustomBusinessMonth(_CustomMixin, BusinessMixin, MonthOffset):
"""
DateOffset subclass representing custom business month(s).

Increments between %(bound)s of month dates.
Increments between {bound} of month dates.

Parameters
----------
Expand Down Expand Up @@ -1284,14 +1285,12 @@ def apply(self, other):
return result


@Substitution(bound="end")
@Appender(_CustomBusinessMonth.__doc__)
@doc(_CustomBusinessMonth, bound="end")
class CustomBusinessMonthEnd(_CustomBusinessMonth):
_prefix = "CBM"


@Substitution(bound="beginning")
@Appender(_CustomBusinessMonth.__doc__)
@doc(_CustomBusinessMonth, bound="beginning")
class CustomBusinessMonthBegin(_CustomBusinessMonth):
_prefix = "CBMS"

Expand Down
39 changes: 19 additions & 20 deletions pandas/util/_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]:
return decorate


def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]:
class doc:
"""
A decorator take docstring templates, concatenate them and perform string
substitution on it.
Expand All @@ -265,37 +265,36 @@ def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]:
The string which would be used to format docstring template.
"""

def decorator(func: F) -> F:
@wraps(func)
def wrapper(*args, **kwargs) -> Callable:
return func(*args, **kwargs)
def __init__(self, *args: Union[str, Callable], **kwargs: str) -> None:
self.appenders = args
self.substitution = kwargs

def __call__(self, func: F) -> F:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does F (FuncType) also represent classes, or just functions? func is now a function or a class (probably worth changing the name).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! I agree here. It has been replaced to callable.

# collecting docstring and docstring templates
docstring_components: List[Union[str, Callable]] = []
if func.__doc__:
docstring_components.append(dedent(func.__doc__))

for arg in args:
if hasattr(arg, "_docstring_components"):
docstring_components.extend(arg._docstring_components) # type: ignore
elif isinstance(arg, str) or arg.__doc__:
docstring_components.append(arg)
for appender in self.appenders:
if hasattr(appender, "_docstring_components"):
docstring_components.extend(
appender._docstring_components # type: ignore
)
elif isinstance(appender, str) or appender.__doc__:
docstring_components.append(appender)

# formatting templates and concatenating docstring
wrapper.__doc__ = "".join(
func.__doc__ = "".join(
[
arg.format(**kwargs)
if isinstance(arg, str)
else dedent(arg.__doc__ or "")
for arg in docstring_components
component.format(**self.substitution)
if isinstance(component, str)
else dedent(component.__doc__ or "")
for component in docstring_components
]
)

wrapper._docstring_components = docstring_components # type: ignore

return cast(F, wrapper)

return decorator
func._docstring_components = docstring_components # type: ignore
return func


# Substitution and Appender are derived from matplotlib.docstring (1.1.0)
Expand Down