From 6e4b0365318d7308aa4cbc697fe08a2af4c20c23 Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Mon, 30 Mar 2020 21:55:22 -0400 Subject: [PATCH 01/10] use doc replace Appender --- pandas/tseries/offsets.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index bc20d784c8dee..11b7ef104d4b3 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -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 @@ -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 ---------- @@ -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" From 21fa0456f2a8cb1b1effc97e54edad225ed8d938 Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Mon, 30 Mar 2020 22:10:09 -0400 Subject: [PATCH 02/10] upgrade doc decorator from function to class --- pandas/util/_decorators.py | 39 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 7a804792174c7..13f8caea46e0b 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -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. @@ -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: # 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) From 363f1be74f3a17c2cbdd185a479b03c8a46e9d1a Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Wed, 1 Apr 2020 19:44:13 -0400 Subject: [PATCH 03/10] convert doc decorator back to function --- pandas/util/_decorators.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 13f8caea46e0b..cb32b7ba5339c 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -245,7 +245,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return decorate -class doc: +def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]: """ A decorator take docstring templates, concatenate them and perform string substitution on it. @@ -265,17 +265,13 @@ class doc: The string which would be used to format docstring template. """ - def __init__(self, *args: Union[str, Callable], **kwargs: str) -> None: - self.appenders = args - self.substitution = kwargs - - def __call__(self, func: F) -> F: + def decorator(func: F) -> F: # collecting docstring and docstring templates docstring_components: List[Union[str, Callable]] = [] if func.__doc__: docstring_components.append(dedent(func.__doc__)) - for appender in self.appenders: + for appender in args: if hasattr(appender, "_docstring_components"): docstring_components.extend( appender._docstring_components # type: ignore @@ -286,7 +282,7 @@ def __call__(self, func: F) -> F: # formatting templates and concatenating docstring func.__doc__ = "".join( [ - component.format(**self.substitution) + component.format(**kwargs) if isinstance(component, str) else dedent(component.__doc__ or "") for component in docstring_components @@ -296,6 +292,8 @@ def __call__(self, func: F) -> F: func._docstring_components = docstring_components # type: ignore return func + return decorator + # Substitution and Appender are derived from matplotlib.docstring (1.1.0) # module https://matplotlib.org/users/license.html From 5b5508de095a7d362c3e65d286d561e03f569d69 Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Wed, 1 Apr 2020 20:53:22 -0400 Subject: [PATCH 04/10] update name and type from function to callable --- pandas/util/_decorators.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index cb32b7ba5339c..feeeef73a6ffc 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -245,13 +245,13 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return decorate -def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]: +def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[Callable], Callable]: """ A decorator take docstring templates, concatenate them and perform string substitution on it. This decorator will add a variable "_docstring_components" to the wrapped - function to keep track the original docstring template for potential usage. + callable to keep track the original docstring template for potential usage. If it should be consider as a template, it will be saved as a string. Otherwise, it will be saved as callable, and later user __doc__ and dedent to get docstring. @@ -260,16 +260,16 @@ def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]: ---------- *args : str or callable The string / docstring / docstring template to be appended in order - after default docstring under function. + after default docstring under callable. **kwags : str The string which would be used to format docstring template. """ - def decorator(func: F) -> F: + def decorator(call: Callable) -> Callable: # collecting docstring and docstring templates docstring_components: List[Union[str, Callable]] = [] - if func.__doc__: - docstring_components.append(dedent(func.__doc__)) + if call.__doc__: + docstring_components.append(dedent(call.__doc__)) for appender in args: if hasattr(appender, "_docstring_components"): @@ -280,7 +280,7 @@ def decorator(func: F) -> F: docstring_components.append(appender) # formatting templates and concatenating docstring - func.__doc__ = "".join( + call.__doc__ = "".join( [ component.format(**kwargs) if isinstance(component, str) @@ -289,8 +289,8 @@ def decorator(func: F) -> F: ] ) - func._docstring_components = docstring_components # type: ignore - return func + call._docstring_components = docstring_components # type: ignore + return call return decorator From eb7d12a802072df28a0001944d3a7201812d3c2a Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Tue, 7 Apr 2020 18:14:27 -0400 Subject: [PATCH 05/10] correct type for decorator --- pandas/util/_decorators.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index feeeef73a6ffc..4cc23c9470fe8 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -245,7 +245,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return decorate -def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[Callable], Callable]: +def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]: """ A decorator take docstring templates, concatenate them and perform string substitution on it. @@ -265,7 +265,7 @@ def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[Callable], Call The string which would be used to format docstring template. """ - def decorator(call: Callable) -> Callable: + def decorator(call: F) -> F: # collecting docstring and docstring templates docstring_components: List[Union[str, Callable]] = [] if call.__doc__: From 1caee8251020ab0432589b1ad7a4c3a1e4698412 Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Tue, 7 Apr 2020 18:21:30 -0400 Subject: [PATCH 06/10] update param names be more descriptive --- pandas/util/_decorators.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 4cc23c9470fe8..a02290323bf5f 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -245,7 +245,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return decorate -def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]: +def doc(*supplements: Union[str, Callable], **substitutes: str) -> Callable[[F], F]: """ A decorator take docstring templates, concatenate them and perform string substitution on it. @@ -258,10 +258,10 @@ def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]: Parameters ---------- - *args : str or callable + *supplements : str or callable The string / docstring / docstring template to be appended in order after default docstring under callable. - **kwags : str + **substitutes : str The string which would be used to format docstring template. """ @@ -271,18 +271,18 @@ def decorator(call: F) -> F: if call.__doc__: docstring_components.append(dedent(call.__doc__)) - for appender in args: - if hasattr(appender, "_docstring_components"): + for supplement in supplements: + if hasattr(supplement, "_docstring_components"): docstring_components.extend( - appender._docstring_components # type: ignore + supplement._docstring_components # type: ignore ) - elif isinstance(appender, str) or appender.__doc__: - docstring_components.append(appender) + elif isinstance(supplement, str) or supplement.__doc__: + docstring_components.append(supplement) # formatting templates and concatenating docstring call.__doc__ = "".join( [ - component.format(**kwargs) + component.format(**substitutes) if isinstance(component, str) else dedent(component.__doc__ or "") for component in docstring_components From d3dbe5d36ccc1b17345881e8d22f59d77b307dc1 Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Wed, 22 Apr 2020 20:32:13 -0400 Subject: [PATCH 07/10] update stacklevel for doc decorator --- pandas/core/arrays/datetimelike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index e3cdc898a88bf..902305dd98a46 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -786,7 +786,7 @@ def shift(self, periods=1, fill_value=None, axis=0): "will raise in a future version, pass " f"{self._scalar_type.__name__} instead.", FutureWarning, - stacklevel=9, + stacklevel=7, ) fill_value = new_fill From faaf5642ac0d1499b47bf1bec0b4c7607128aabc Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Wed, 22 Apr 2020 21:11:11 -0400 Subject: [PATCH 08/10] update arg names in doc decorator --- pandas/util/_decorators.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 555f9fcaa1b01..097370be114de 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -329,7 +329,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return decorate -def doc(*supplements: Union[str, Callable], **substitutes: str) -> Callable[[F], F]: +def doc(*docstrings: Union[str, Callable], **params: str) -> Callable[[F], F]: """ A decorator take docstring templates, concatenate them and perform string substitution on it. @@ -342,39 +342,39 @@ def doc(*supplements: Union[str, Callable], **substitutes: str) -> Callable[[F], Parameters ---------- - *supplements : str or callable + *docstrings : str or callable The string / docstring / docstring template to be appended in order after default docstring under callable. - **substitutes : str + **params : str The string which would be used to format docstring template. """ - def decorator(call: F) -> F: + def decorator(decorated: F) -> F: # collecting docstring and docstring templates docstring_components: List[Union[str, Callable]] = [] - if call.__doc__: - docstring_components.append(dedent(call.__doc__)) + if decorated.__doc__: + docstring_components.append(dedent(decorated.__doc__)) - for supplement in supplements: - if hasattr(supplement, "_docstring_components"): + for docstring in docstrings: + if hasattr(docstring, "_docstring_components"): docstring_components.extend( - supplement._docstring_components # type: ignore + docstring._docstring_components # type: ignore ) - elif isinstance(supplement, str) or supplement.__doc__: - docstring_components.append(supplement) + elif isinstance(docstring, str) or docstring.__doc__: + docstring_components.append(docstring) # formatting templates and concatenating docstring - call.__doc__ = "".join( + decorated.__doc__ = "".join( [ - component.format(**substitutes) + component.format(**params) if isinstance(component, str) else dedent(component.__doc__ or "") for component in docstring_components ] ) - call._docstring_components = docstring_components # type: ignore - return call + decorated._docstring_components = docstring_components # type: ignore + return decorated return decorator From 08a074431fcaeb4a9675ff8093fb910ea1f8fb8c Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Sun, 17 May 2020 22:42:45 -0400 Subject: [PATCH 09/10] remove ignore to fix mypy error --- pandas/core/indexes/base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 8751cca97c18c..b952a6f9d917d 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -54,7 +54,6 @@ ABCCategorical, ABCDataFrame, ABCDatetimeIndex, - ABCIntervalIndex, ABCMultiIndex, ABCPandasArray, ABCPeriodIndex, @@ -872,7 +871,7 @@ def _format_data(self, name=None) -> str_t: if self.inferred_type == "string": is_justify = False elif self.inferred_type == "categorical": - if is_object_dtype(self.categories): # type: ignore + if is_object_dtype(self.categories): is_justify = False return format_object_summary( From 11de122a0916248ac7ea9dd33fc1b2da0f81bb90 Mon Sep 17 00:00:00 2001 From: HH-MWB Date: Sun, 17 May 2020 23:26:01 -0400 Subject: [PATCH 10/10] fix mypy error --- pandas/core/indexes/base.py | 2 +- pandas/util/_decorators.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index b952a6f9d917d..d9828707b6164 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -871,7 +871,7 @@ def _format_data(self, name=None) -> str_t: if self.inferred_type == "string": is_justify = False elif self.inferred_type == "categorical": - if is_object_dtype(self.categories): + if is_object_dtype(self.categories): # type: ignore is_justify = False return format_object_summary( diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 7799c1e29795a..6135ccba1573d 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -329,7 +329,7 @@ def wrapper(*args, **kwargs) -> Callable[..., Any]: return decorate -def doc(*docstrings: Union[str, Callable], **params: str) -> Callable[[F], F]: +def doc(*docstrings: Union[str, Callable], **params) -> Callable[[F], F]: """ A decorator take docstring templates, concatenate them and perform string substitution on it. @@ -345,7 +345,7 @@ def doc(*docstrings: Union[str, Callable], **params: str) -> Callable[[F], F]: *docstrings : str or callable The string / docstring / docstring template to be appended in order after default docstring under callable. - **params : str + **params The string which would be used to format docstring template. """