Skip to content

Commit 091cd7e

Browse files
HH-MWBSeeminSyed
authored andcommitted
CLN: @doc - base.py & indexing.py (pandas-dev#31970)
1 parent 911cb72 commit 091cd7e

File tree

7 files changed

+51
-38
lines changed

7 files changed

+51
-38
lines changed

pandas/core/arrays/categorical.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
Substitution,
1616
cache_readonly,
1717
deprecate_kwarg,
18+
doc,
1819
)
1920
from pandas.util._validators import validate_bool_kwarg, validate_fillna_kwargs
2021

@@ -1352,8 +1353,7 @@ def memory_usage(self, deep=False):
13521353
"""
13531354
return self._codes.nbytes + self.dtype.categories.memory_usage(deep=deep)
13541355

1355-
@Substitution(klass="Categorical")
1356-
@Appender(_shared_docs["searchsorted"])
1356+
@doc(_shared_docs["searchsorted"], klass="Categorical")
13571357
def searchsorted(self, value, side="left", sorter=None):
13581358
# searchsorted is very performance sensitive. By converting codes
13591359
# to same dtype as self.codes, we get much faster performance.

pandas/core/base.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from pandas.compat import PYPY
1313
from pandas.compat.numpy import function as nv
1414
from pandas.errors import AbstractMethodError
15-
from pandas.util._decorators import Appender, Substitution, cache_readonly, doc
15+
from pandas.util._decorators import cache_readonly, doc
1616
from pandas.util._validators import validate_bool_kwarg
1717

1818
from pandas.core.dtypes.cast import is_nested_object
@@ -1425,21 +1425,21 @@ def factorize(self, sort=False, na_sentinel=-1):
14251425
] = """
14261426
Find indices where elements should be inserted to maintain order.
14271427
1428-
Find the indices into a sorted %(klass)s `self` such that, if the
1428+
Find the indices into a sorted {klass} `self` such that, if the
14291429
corresponding elements in `value` were inserted before the indices,
14301430
the order of `self` would be preserved.
14311431
14321432
.. note::
14331433
1434-
The %(klass)s *must* be monotonically sorted, otherwise
1434+
The {klass} *must* be monotonically sorted, otherwise
14351435
wrong locations will likely be returned. Pandas does *not*
14361436
check this for you.
14371437
14381438
Parameters
14391439
----------
14401440
value : array_like
14411441
Values to insert into `self`.
1442-
side : {'left', 'right'}, optional
1442+
side : {{'left', 'right'}}, optional
14431443
If 'left', the index of the first suitable location found is given.
14441444
If 'right', return the last such index. If there is no suitable
14451445
index, return either 0 or N (where N is the length of `self`).
@@ -1515,8 +1515,7 @@ def factorize(self, sort=False, na_sentinel=-1):
15151515
0 # wrong result, correct would be 1
15161516
"""
15171517

1518-
@Substitution(klass="Index")
1519-
@Appender(_shared_docs["searchsorted"])
1518+
@doc(_shared_docs["searchsorted"], klass="Index")
15201519
def searchsorted(self, value, side="left", sorter=None) -> np.ndarray:
15211520
return algorithms.searchsorted(self._values, value, side=side, sorter=sorter)
15221521

pandas/core/indexes/datetimelike.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from pandas._typing import Label
1212
from pandas.compat.numpy import function as nv
1313
from pandas.errors import AbstractMethodError
14-
from pandas.util._decorators import Appender, cache_readonly
14+
from pandas.util._decorators import Appender, cache_readonly, doc
1515

1616
from pandas.core.dtypes.common import (
1717
ensure_int64,
@@ -30,7 +30,7 @@
3030
from pandas.core import algorithms
3131
from pandas.core.arrays import DatetimeArray, PeriodArray, TimedeltaArray
3232
from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin
33-
from pandas.core.base import _shared_docs
33+
from pandas.core.base import IndexOpsMixin
3434
import pandas.core.indexes.base as ibase
3535
from pandas.core.indexes.base import Index, _index_shared_docs
3636
from pandas.core.indexes.extension import (
@@ -205,7 +205,7 @@ def take(self, indices, axis=0, allow_fill=True, fill_value=None, **kwargs):
205205
self, indices, axis, allow_fill, fill_value, **kwargs
206206
)
207207

208-
@Appender(_shared_docs["searchsorted"])
208+
@doc(IndexOpsMixin.searchsorted, klass="Datetime-like Index")
209209
def searchsorted(self, value, side="left", sorter=None):
210210
if isinstance(value, str):
211211
raise TypeError(

pandas/core/indexing.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from pandas._libs.indexing import _NDFrameIndexerBase
66
from pandas._libs.lib import item_from_zerodim
77
from pandas.errors import AbstractMethodError
8-
from pandas.util._decorators import Appender
8+
from pandas.util._decorators import doc
99

1010
from pandas.core.dtypes.common import (
1111
is_hashable,
@@ -887,7 +887,7 @@ def _getbool_axis(self, key, axis: int):
887887
return self.obj._take_with_is_copy(inds, axis=axis)
888888

889889

890-
@Appender(IndexingMixin.loc.__doc__)
890+
@doc(IndexingMixin.loc)
891891
class _LocIndexer(_LocationIndexer):
892892
_takeable: bool = False
893893
_valid_types = (
@@ -899,7 +899,7 @@ class _LocIndexer(_LocationIndexer):
899899
# -------------------------------------------------------------------
900900
# Key Checks
901901

902-
@Appender(_LocationIndexer._validate_key.__doc__)
902+
@doc(_LocationIndexer._validate_key)
903903
def _validate_key(self, key, axis: int):
904904

905905
# valid for a collection of labels (we check their presence later)
@@ -1329,7 +1329,7 @@ def _validate_read_indexer(
13291329
)
13301330

13311331

1332-
@Appender(IndexingMixin.iloc.__doc__)
1332+
@doc(IndexingMixin.iloc)
13331333
class _iLocIndexer(_LocationIndexer):
13341334
_valid_types = (
13351335
"integer, integer slice (START point is INCLUDED, END "
@@ -2048,7 +2048,7 @@ def __setitem__(self, key, value):
20482048
self.obj._set_value(*key, value=value, takeable=self._takeable)
20492049

20502050

2051-
@Appender(IndexingMixin.at.__doc__)
2051+
@doc(IndexingMixin.at)
20522052
class _AtIndexer(_ScalarAccessIndexer):
20532053
_takeable = False
20542054

@@ -2074,7 +2074,7 @@ def __getitem__(self, key):
20742074
return obj.index._get_values_for_loc(obj, loc, key)
20752075

20762076

2077-
@Appender(IndexingMixin.iat.__doc__)
2077+
@doc(IndexingMixin.iat)
20782078
class _iAtIndexer(_ScalarAccessIndexer):
20792079
_takeable = True
20802080

pandas/core/series.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -2492,8 +2492,7 @@ def __rmatmul__(self, other):
24922492
"""
24932493
return self.dot(np.transpose(other))
24942494

2495-
@Substitution(klass="Series")
2496-
@Appender(base._shared_docs["searchsorted"])
2495+
@doc(base.IndexOpsMixin.searchsorted, klass="Series")
24972496
def searchsorted(self, value, side="left", sorter=None):
24982497
return algorithms.searchsorted(self._values, value, side=side, sorter=sorter)
24992498

pandas/tests/util/test_doc.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ def cumsum(whatever):
1414

1515
@doc(
1616
cumsum,
17-
"""
18-
Examples
19-
--------
17+
dedent(
18+
"""
19+
Examples
20+
--------
2021
21-
>>> cumavg([1, 2, 3])
22-
2
23-
""",
22+
>>> cumavg([1, 2, 3])
23+
2
24+
"""
25+
),
2426
method="cumavg",
2527
operation="average",
2628
)

pandas/util/_decorators.py

+26-13
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,11 @@ def doc(*args: Union[str, Callable], **kwargs: str) -> Callable[[F], F]:
250250
A decorator take docstring templates, concatenate them and perform string
251251
substitution on it.
252252
253-
This decorator is robust even if func.__doc__ is None. This decorator will
254-
add a variable "_docstr_template" to the wrapped function to save original
255-
docstring template for potential usage.
253+
This decorator will add a variable "_docstring_components" to the wrapped
254+
function to keep track the original docstring template for potential usage.
255+
If it should be consider as a template, it will be saved as a string.
256+
Otherwise, it will be saved as callable, and later user __doc__ and dedent
257+
to get docstring.
256258
257259
Parameters
258260
----------
@@ -268,17 +270,28 @@ def decorator(func: F) -> F:
268270
def wrapper(*args, **kwargs) -> Callable:
269271
return func(*args, **kwargs)
270272

271-
templates = [func.__doc__ if func.__doc__ else ""]
273+
# collecting docstring and docstring templates
274+
docstring_components: List[Union[str, Callable]] = []
275+
if func.__doc__:
276+
docstring_components.append(dedent(func.__doc__))
277+
272278
for arg in args:
273-
if isinstance(arg, str):
274-
templates.append(arg)
275-
elif hasattr(arg, "_docstr_template"):
276-
templates.append(arg._docstr_template) # type: ignore
277-
elif arg.__doc__:
278-
templates.append(arg.__doc__)
279-
280-
wrapper._docstr_template = "".join(dedent(t) for t in templates) # type: ignore
281-
wrapper.__doc__ = wrapper._docstr_template.format(**kwargs) # type: ignore
279+
if hasattr(arg, "_docstring_components"):
280+
docstring_components.extend(arg._docstring_components) # type: ignore
281+
elif isinstance(arg, str) or arg.__doc__:
282+
docstring_components.append(arg)
283+
284+
# formatting templates and concatenating docstring
285+
wrapper.__doc__ = "".join(
286+
[
287+
arg.format(**kwargs)
288+
if isinstance(arg, str)
289+
else dedent(arg.__doc__ or "")
290+
for arg in docstring_components
291+
]
292+
)
293+
294+
wrapper._docstring_components = docstring_components # type: ignore
282295

283296
return cast(F, wrapper)
284297

0 commit comments

Comments
 (0)