Skip to content

Commit 1d32264

Browse files
datapythonistajreback
authored andcommittedJan 6, 2018
DOC: Using deprecated sphinx directive instead of non-standard messages in docstrings (#18928) (#18934)
1 parent 5bd0836 commit 1d32264

19 files changed

+204
-100
lines changed
 

‎ci/lint.sh

+4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ if [ "$LINT" ]; then
117117
fi
118118
done
119119
echo "Check for incorrect sphinx directives DONE"
120+
121+
echo "Check for deprecated messages without sphinx directive"
122+
grep -R --include="*.py" --include="*.pyx" -E "(DEPRECATED|DEPRECATE|Deprecated)(:|,|\.)" pandas
123+
echo "Check for deprecated messages without sphinx directive DONE"
120124
else
121125
echo "NOT Linting"
122126
fi

‎doc/source/contributing.rst

+24-1
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,30 @@ Backwards Compatibility
547547
Please try to maintain backward compatibility. *pandas* has lots of users with lots of
548548
existing code, so don't break it if at all possible. If you think breakage is required,
549549
clearly state why as part of the pull request. Also, be careful when changing method
550-
signatures and add deprecation warnings where needed.
550+
signatures and add deprecation warnings where needed. Also, add the deprecated sphinx
551+
directive to the deprecated functions or methods.
552+
553+
If a function with the same arguments as the one being deprecated exist, you can use
554+
the ``pandas.util._decorators.deprecate``:
555+
556+
.. code-block:: python
557+
558+
from pandas.util._decorators import deprecate
559+
560+
deprecate('old_func', 'new_func', '0.21.0')
561+
562+
Otherwise, you need to do it manually:
563+
564+
.. code-block:: python
565+
566+
def old_func():
567+
"""Summary of the function.
568+
569+
.. deprecated:: 0.21.0
570+
Use new_func instead.
571+
"""
572+
warnings.warn('Use new_func instead.', FutureWarning, stacklevel=2)
573+
new_func()
551574
552575
.. _contributing.ci:
553576

‎pandas/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
plot_params = pandas.plotting._style._Options(deprecated=True)
5252
# do not import deprecate to top namespace
5353
scatter_matrix = pandas.util._decorators.deprecate(
54-
'pandas.scatter_matrix', pandas.plotting.scatter_matrix,
54+
'pandas.scatter_matrix', pandas.plotting.scatter_matrix, '0.20.0',
5555
'pandas.plotting.scatter_matrix')
5656

5757
from pandas.util._print_versions import show_versions

‎pandas/_libs/tslibs/timestamps.pyx

-3
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,6 @@ class Timestamp(_Timestamp):
389389
Unit used for conversion if ts_input is of type int or float. The
390390
valid values are 'D', 'h', 'm', 's', 'ms', 'us', and 'ns'. For
391391
example, 's' means seconds and 'ms' means milliseconds.
392-
offset : str, DateOffset
393-
Deprecated, use freq
394-
395392
year, month, day : int
396393
.. versionadded:: 0.19.0
397394
hour, minute, second, microsecond : int, optional, default 0

‎pandas/computation/expressions.py

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33

44
def set_use_numexpr(v=True):
5+
"""
6+
.. deprecated:: 0.20.0
7+
Use ``pandas.set_option('compute.use_numexpr', v)`` instead.
8+
"""
59
warnings.warn("pandas.computation.expressions.set_use_numexpr is "
610
"deprecated and will be removed in a future version.\n"
711
"you can toggle usage of numexpr via "

‎pandas/core/categorical.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,8 @@ def _get_labels(self):
594594
"""
595595
Get the category labels (deprecated).
596596
597-
Deprecated, use .codes!
597+
.. deprecated:: 0.15.0
598+
Use `.codes()` instead.
598599
"""
599600
warn("'labels' is deprecated. Use 'codes' instead", FutureWarning,
600601
stacklevel=2)

‎pandas/core/datetools.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
"""A collection of random tools for dealing with dates in Python"""
1+
"""A collection of random tools for dealing with dates in Python.
2+
3+
.. deprecated:: 0.19.0
4+
Use pandas.tseries module instead.
5+
"""
26

37
# flake8: noqa
48

‎pandas/core/dtypes/common.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -758,10 +758,9 @@ def is_dtype_union_equal(source, target):
758758

759759

760760
def is_any_int_dtype(arr_or_dtype):
761-
"""
762-
DEPRECATED: This function will be removed in a future version.
761+
"""Check whether the provided array or dtype is of an integer dtype.
763762
764-
Check whether the provided array or dtype is of an integer dtype.
763+
.. deprecated:: 0.20.0
765764
766765
In this function, timedelta64 instances are also considered "any-integer"
767766
type objects and will return True.
@@ -1557,12 +1556,11 @@ def is_float_dtype(arr_or_dtype):
15571556

15581557

15591558
def is_floating_dtype(arr_or_dtype):
1560-
"""
1561-
DEPRECATED: This function will be removed in a future version.
1562-
1563-
Check whether the provided array or dtype is an instance of
1559+
"""Check whether the provided array or dtype is an instance of
15641560
numpy's float dtype.
15651561
1562+
.. deprecated:: 0.20.0
1563+
15661564
Unlike, `is_float_dtype`, this check is a lot stricter, as it requires
15671565
`isinstance` of `np.floating` and not `issubclass`.
15681566
"""

‎pandas/core/frame.py

+14-16
Original file line numberDiff line numberDiff line change
@@ -1326,9 +1326,10 @@ def _from_arrays(cls, arrays, columns, index, dtype=None):
13261326
def from_csv(cls, path, header=0, sep=',', index_col=0, parse_dates=True,
13271327
encoding=None, tupleize_cols=None,
13281328
infer_datetime_format=False):
1329-
"""
1330-
Read CSV file (DEPRECATED, please use :func:`pandas.read_csv`
1331-
instead).
1329+
"""Read CSV file.
1330+
1331+
.. deprecated:: 0.21.0
1332+
Use :func:`pandas.read_csv` instead.
13321333
13331334
It is preferable to use the more powerful :func:`pandas.read_csv`
13341335
for most general purposes, but ``from_csv`` makes for an easy
@@ -1979,12 +1980,10 @@ def _unpickle_matrix_compat(self, state): # pragma: no cover
19791980
# Getting and setting elements
19801981

19811982
def get_value(self, index, col, takeable=False):
1982-
"""
1983-
Quickly retrieve single value at passed column and index
1983+
"""Quickly retrieve single value at passed column and index
19841984
19851985
.. deprecated:: 0.21.0
1986-
1987-
Please use .at[] or .iat[] accessors.
1986+
Use .at[] or .iat[] accessors instead.
19881987
19891988
Parameters
19901989
----------
@@ -2024,12 +2023,10 @@ def _get_value(self, index, col, takeable=False):
20242023
_get_value.__doc__ = get_value.__doc__
20252024

20262025
def set_value(self, index, col, value, takeable=False):
2027-
"""
2028-
Put single value at passed column and index
2026+
"""Put single value at passed column and index
20292027
20302028
.. deprecated:: 0.21.0
2031-
2032-
Please use .at[] or .iat[] accessors.
2029+
Use .at[] or .iat[] accessors instead.
20332030
20342031
Parameters
20352032
----------
@@ -3737,12 +3734,13 @@ def sort_index(self, axis=0, level=None, ascending=True, inplace=False,
37373734

37383735
def sortlevel(self, level=0, axis=0, ascending=True, inplace=False,
37393736
sort_remaining=True):
3740-
"""
3741-
DEPRECATED: use :meth:`DataFrame.sort_index`
3742-
3743-
Sort multilevel index by chosen axis and primary level. Data will be
3737+
"""Sort multilevel index by chosen axis and primary level. Data will be
37443738
lexicographically sorted by the chosen level followed by the other
3745-
levels (in order)
3739+
levels (in order).
3740+
3741+
.. deprecated:: 0.20.0
3742+
Use :meth:`DataFrame.sort_index`
3743+
37463744
37473745
Parameters
37483746
----------

‎pandas/core/generic.py

+14-13
Original file line numberDiff line numberDiff line change
@@ -2718,10 +2718,10 @@ def xs(self, key, axis=0, level=None, drop_level=True):
27182718
_xs = xs
27192719

27202720
def select(self, crit, axis=0):
2721-
"""
2722-
Return data corresponding to axis labels matching criteria
2721+
"""Return data corresponding to axis labels matching criteria
27232722
2724-
DEPRECATED: use df.loc[df.index.map(crit)] to select via labels
2723+
.. deprecated:: 0.21.0
2724+
Use df.loc[df.index.map(crit)] to select via labels
27252725
27262726
Parameters
27272727
----------
@@ -4108,8 +4108,11 @@ def _consolidate(self, inplace=False):
41084108
return self._constructor(cons_data).__finalize__(self)
41094109

41104110
def consolidate(self, inplace=False):
4111-
"""
4112-
DEPRECATED: consolidate will be an internal implementation only.
4111+
"""Compute NDFrame with "consolidated" internals (data of each dtype
4112+
grouped together in a single ndarray).
4113+
4114+
.. deprecated:: 0.20.0
4115+
Consolidate will be an internal implementation only.
41134116
"""
41144117
# 15483
41154118
warnings.warn("consolidate is deprecated and will be removed in a "
@@ -4160,11 +4163,10 @@ def _get_bool_data(self):
41604163
# Internal Interface Methods
41614164

41624165
def as_matrix(self, columns=None):
4163-
"""
4164-
DEPRECATED: as_matrix will be removed in a future version.
4165-
Use :meth:`DataFrame.values` instead.
4166+
"""Convert the frame to its Numpy-array representation.
41664167
4167-
Convert the frame to its Numpy-array representation.
4168+
.. deprecated:: 0.23.0
4169+
Use :meth:`DataFrame.values` instead.
41684170
41694171
Parameters
41704172
----------
@@ -4479,12 +4481,11 @@ def _convert(self, datetime=False, numeric=False, timedelta=False,
44794481
timedelta=timedelta, coerce=coerce,
44804482
copy=copy)).__finalize__(self)
44814483

4482-
# TODO: Remove in 0.18 or 2017, which ever is sooner
44834484
def convert_objects(self, convert_dates=True, convert_numeric=False,
44844485
convert_timedeltas=True, copy=True):
4485-
"""
4486-
Deprecated.
4487-
Attempt to infer better dtype for object columns
4486+
"""Attempt to infer better dtype for object columns.
4487+
4488+
.. deprecated:: 0.21.0
44884489
44894490
Parameters
44904491
----------

‎pandas/core/indexes/datetimelike.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,10 @@ def _isnan(self):
441441

442442
@property
443443
def asobject(self):
444-
"""DEPRECATED: Use ``astype(object)`` instead.
444+
"""Return object Index which contains boxed values.
445445
446-
return object Index which contains boxed values
446+
.. deprecated:: 0.23.0
447+
Use ``astype(object)`` instead.
447448
448449
*this is an internal non-public method*
449450
"""

‎pandas/core/panel.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -477,8 +477,7 @@ def as_matrix(self):
477477
# Getting and setting elements
478478

479479
def get_value(self, *args, **kwargs):
480-
"""
481-
Quickly retrieve single value at (item, major, minor) location
480+
"""Quickly retrieve single value at (item, major, minor) location
482481
483482
.. deprecated:: 0.21.0
484483
@@ -525,8 +524,7 @@ def _get_value(self, *args, **kwargs):
525524
_get_value.__doc__ = get_value.__doc__
526525

527526
def set_value(self, *args, **kwargs):
528-
"""
529-
Quickly set single value at (item, major, minor) location
527+
"""Quickly set single value at (item, major, minor) location
530528
531529
.. deprecated:: 0.21.0
532530

‎pandas/core/series.py

+39-29
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,10 @@
9393

9494
# see gh-16971
9595
def remove_na(arr):
96-
"""
97-
DEPRECATED : this function will be removed in a future version.
96+
"""Remove null values from array like structure.
97+
98+
.. deprecated:: 0.21.0
99+
Use s[s.notnull()] instead.
98100
"""
99101

100102
warnings.warn("remove_na is deprecated and is a private "
@@ -290,8 +292,10 @@ def _init_dict(self, data, index=None, dtype=None):
290292
@classmethod
291293
def from_array(cls, arr, index=None, name=None, dtype=None, copy=False,
292294
fastpath=False):
293-
"""
294-
DEPRECATED: use the pd.Series(..) constructor instead.
295+
"""Construct Series from array.
296+
297+
.. deprecated :: 0.23.0
298+
Use pd.Series(..) constructor instead.
295299
296300
"""
297301
warnings.warn("'from_array' is deprecated and will be removed in a "
@@ -450,9 +454,11 @@ def get_values(self):
450454

451455
@property
452456
def asobject(self):
453-
"""DEPRECATED: Use ``astype(object)`` instead.
457+
"""Return object Series which contains boxed values.
458+
459+
.. deprecated :: 0.23.0
460+
Use ``astype(object) instead.
454461
455-
return object Series which contains boxed values
456462
457463
*this is an internal non-public method*
458464
"""
@@ -911,12 +917,10 @@ def repeat(self, repeats, *args, **kwargs):
911917
index=new_index).__finalize__(self)
912918

913919
def get_value(self, label, takeable=False):
914-
"""
915-
Quickly retrieve single value at passed index label
920+
"""Quickly retrieve single value at passed index label
916921
917922
.. deprecated:: 0.21.0
918-
919-
Please use .at[] or .iat[] accessors.
923+
Please use .at[] or .iat[] accessors.
920924
921925
Parameters
922926
----------
@@ -940,14 +944,12 @@ def _get_value(self, label, takeable=False):
940944
_get_value.__doc__ = get_value.__doc__
941945

942946
def set_value(self, label, value, takeable=False):
943-
"""
944-
Quickly set single value at passed label. If label is not contained, a
945-
new object is created with the label placed at the end of the result
946-
index
947+
"""Quickly set single value at passed label. If label is not contained,
948+
a new object is created with the label placed at the end of the result
949+
index.
947950
948951
.. deprecated:: 0.21.0
949-
950-
Please use .at[] or .iat[] accessors.
952+
Please use .at[] or .iat[] accessors.
951953
952954
Parameters
953955
----------
@@ -1382,13 +1384,13 @@ def idxmax(self, axis=None, skipna=True, *args, **kwargs):
13821384
return self.index[i]
13831385

13841386
# ndarray compat
1385-
argmin = deprecate('argmin', idxmin,
1387+
argmin = deprecate('argmin', idxmin, '0.21.0',
13861388
msg="'argmin' is deprecated, use 'idxmin' instead. "
13871389
"The behavior of 'argmin' will be corrected to "
13881390
"return the positional minimum in the future. "
13891391
"Use 'series.values.argmin' to get the position of "
13901392
"the minimum now.")
1391-
argmax = deprecate('argmax', idxmax,
1393+
argmax = deprecate('argmax', idxmax, '0.21.0',
13921394
msg="'argmax' is deprecated, use 'idxmax' instead. "
13931395
"The behavior of 'argmax' will be corrected to "
13941396
"return the positional maximum in the future. "
@@ -2120,12 +2122,12 @@ def nsmallest(self, n=5, keep='first'):
21202122
return algorithms.SelectNSeries(self, n=n, keep=keep).nsmallest()
21212123

21222124
def sortlevel(self, level=0, ascending=True, sort_remaining=True):
2123-
"""
2124-
DEPRECATED: use :meth:`Series.sort_index`
2125-
2126-
Sort Series with MultiIndex by chosen level. Data will be
2125+
"""Sort Series with MultiIndex by chosen level. Data will be
21272126
lexicographically sorted by the chosen level followed by the other
2128-
levels (in order)
2127+
levels (in order),
2128+
2129+
.. deprecated:: 0.20.0
2130+
Use :meth:`Series.sort_index`
21292131
21302132
Parameters
21312133
----------
@@ -2670,7 +2672,12 @@ def shift(self, periods=1, freq=None, axis=0):
26702672
return super(Series, self).shift(periods=periods, freq=freq, axis=axis)
26712673

26722674
def reindex_axis(self, labels, axis=0, **kwargs):
2673-
""" for compatibility with higher dims """
2675+
"""Conform Series to new index with optional filling logic.
2676+
2677+
.. deprecated:: 0.21.0
2678+
Use ``Series.reindex`` instead.
2679+
"""
2680+
# for compatibility with higher dims
26742681
if axis != 0:
26752682
raise ValueError("cannot reindex series on non-zero axis!")
26762683
msg = ("'.reindex_axis' is deprecated and will be removed in a future "
@@ -2808,9 +2815,10 @@ def between(self, left, right, inclusive=True):
28082815
@classmethod
28092816
def from_csv(cls, path, sep=',', parse_dates=True, header=None,
28102817
index_col=0, encoding=None, infer_datetime_format=False):
2811-
"""
2812-
Read CSV file (DEPRECATED, please use :func:`pandas.read_csv`
2813-
instead).
2818+
"""Read CSV file.
2819+
2820+
.. deprecated:: 0.21.0
2821+
Use :func:`pandas.read_csv` instead.
28142822
28152823
It is preferable to use the more powerful :func:`pandas.read_csv`
28162824
for most general purposes, but ``from_csv`` makes for an easy
@@ -2978,8 +2986,10 @@ def dropna(self, axis=0, inplace=False, **kwargs):
29782986
return self.copy()
29792987

29802988
def valid(self, inplace=False, **kwargs):
2981-
"""DEPRECATED. Series.valid will be removed in a future version.
2982-
Use :meth:`Series.dropna` instead.
2989+
"""Return Series without null values.
2990+
2991+
.. deprecated:: 0.23.0
2992+
Use :meth:`Series.dropna` instead.
29832993
"""
29842994
warnings.warn("Method .valid will be removed in a future version. "
29852995
"Use .dropna instead.", FutureWarning, stacklevel=2)

‎pandas/core/sparse/frame.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -820,12 +820,12 @@ def cumsum(self, axis=0, *args, **kwargs):
820820

821821
return self.apply(lambda x: x.cumsum(), axis=axis)
822822

823-
@Appender(generic._shared_docs['isna'])
823+
@Appender(generic._shared_docs['isna'] % _shared_doc_kwargs)
824824
def isna(self):
825825
return self._apply_columns(lambda x: x.isna())
826826
isnull = isna
827827

828-
@Appender(generic._shared_docs['notna'])
828+
@Appender(generic._shared_docs['notna'] % _shared_doc_kwargs)
829829
def notna(self):
830830
return self._apply_columns(lambda x: x.notna())
831831
notnull = notna

‎pandas/core/sparse/series.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,10 @@ def npoints(self):
255255
@classmethod
256256
def from_array(cls, arr, index=None, name=None, copy=False,
257257
fill_value=None, fastpath=False):
258-
"""
259-
DEPRECATED: use the pd.SparseSeries(..) constructor instead.
258+
"""Construct SparseSeries from array.
260259
260+
.. deprecated:: 0.23.0
261+
Use the pd.SparseSeries(..) constructor instead.
261262
"""
262263
warnings.warn("'from_array' is deprecated and will be removed in a "
263264
"future version. Please use the pd.SparseSeries(..) "
@@ -571,8 +572,9 @@ def to_dense(self, sparse_only=False):
571572
572573
Parameters
573574
----------
574-
sparse_only: bool, default False
575-
DEPRECATED: this argument will be removed in a future version.
575+
sparse_only : bool, default False
576+
.. deprecated:: 0.20.0
577+
This argument will be removed in a future version.
576578
577579
If True, return just the non-sparse values, or the dense version
578580
of `self.values` if False.
@@ -679,15 +681,15 @@ def cumsum(self, axis=0, *args, **kwargs):
679681
new_array, index=self.index,
680682
sparse_index=new_array.sp_index).__finalize__(self)
681683

682-
@Appender(generic._shared_docs['isna'])
684+
@Appender(generic._shared_docs['isna'] % _shared_doc_kwargs)
683685
def isna(self):
684686
arr = SparseArray(isna(self.values.sp_values),
685687
sparse_index=self.values.sp_index,
686688
fill_value=isna(self.fill_value))
687689
return self._constructor(arr, index=self.index).__finalize__(self)
688690
isnull = isna
689691

690-
@Appender(generic._shared_docs['notna'])
692+
@Appender(generic._shared_docs['notna'] % _shared_doc_kwargs)
691693
def notna(self):
692694
arr = SparseArray(notna(self.values.sp_values),
693695
sparse_index=self.values.sp_index,

‎pandas/core/strings.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,8 @@ def str_match(arr, pat, case=True, flags=0, na=np.nan, as_indexer=None):
478478
flags : int, default 0 (no flags)
479479
re module flags, e.g. re.IGNORECASE
480480
na : default NaN, fill value for missing values.
481-
as_indexer : DEPRECATED - Keyword is ignored.
481+
as_indexer
482+
.. deprecated:: 0.21.0
482483
483484
Returns
484485
-------

‎pandas/util/_decorators.py

+24-9
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,24 @@
77
from functools import wraps, update_wrapper
88

99

10-
def deprecate(name, alternative, alt_name=None, klass=None,
11-
stacklevel=2, msg=None):
12-
"""
13-
Return a new function that emits a deprecation warning on use.
10+
def deprecate(name, alternative, version, alt_name=None,
11+
klass=None, stacklevel=2, msg=None):
12+
"""Return a new function that emits a deprecation warning on use.
13+
14+
To use this method for a deprecated function, another function
15+
`alternative` with the same signature must exist. The deprecated
16+
function will emit a deprecation warning, and in the docstring
17+
it will contain the deprecation directive with the provided version
18+
so it can be detected for future removal.
1419
1520
Parameters
1621
----------
1722
name : str
1823
Name of function to deprecate
1924
alternative : str
2025
Name of function to use instead
26+
version : str
27+
Version of pandas in which the method has been deprecated
2128
alt_name : str, optional
2229
Name to use in preference of alternative.__name__
2330
klass : Warning, default FutureWarning
@@ -29,16 +36,24 @@ def deprecate(name, alternative, alt_name=None, klass=None,
2936

3037
alt_name = alt_name or alternative.__name__
3138
klass = klass or FutureWarning
32-
msg = msg or "{} is deprecated, use {} instead".format(name, alt_name)
39+
warning_msg = msg or '{} is deprecated, use {} instead'.format(name,
40+
alt_name)
3341

3442
@wraps(alternative)
3543
def wrapper(*args, **kwargs):
36-
warnings.warn(msg, klass, stacklevel=stacklevel)
44+
warnings.warn(warning_msg, klass, stacklevel=stacklevel)
3745
return alternative(*args, **kwargs)
3846

39-
if getattr(wrapper, '__doc__', None) is not None:
40-
wrapper.__doc__ = ('\n'.join(wrap(msg, 70)) + '\n'
41-
+ dedent(wrapper.__doc__))
47+
# adding deprecated directive to the docstring
48+
msg = msg or 'Use `{alt_name}` instead.'
49+
docstring = '.. deprecated:: {}\n'.format(version)
50+
docstring += dedent(' ' + ('\n'.join(wrap(msg, 70))))
51+
52+
if getattr(wrapper, '__doc__') is not None:
53+
docstring += dedent(wrapper.__doc__)
54+
55+
wrapper.__doc__ = docstring
56+
4257
return wrapper
4358

4459

‎scripts/announce.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
3131
From the bash command line with $GITHUB token.
3232
33-
$ ./scripts/announce $GITHUB v1.11.0..v1.11.1 > announce.rst
33+
$ ./scripts/announce.py $GITHUB v1.11.0..v1.11.1 > announce.rst
3434
3535
"""
3636
from __future__ import print_function, division

‎scripts/api_rst_coverage.py

100644100755
+50-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,22 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
"""
4+
Script to generate a report with the coverage of the API in the docs.
5+
6+
The output of this script shows the existing methods that are not
7+
included in the API documentation, as well as the methods documented
8+
that do not exist. Ideally, no method should be listed. Currently it
9+
considers the methods of Series, DataFrame and Panel.
10+
11+
Deprecated methods are usually removed from the documentation, while
12+
still available for three minor versions. They are listed with the
13+
word deprecated and the version number next to them.
14+
15+
Usage::
16+
17+
$ PYTHONPATH=.. ./api_rst_coverage.py
18+
19+
"""
120
import pandas as pd
221
import inspect
322
import re
@@ -13,6 +32,32 @@ def class_name_sort_key(x):
1332
else:
1433
return x
1534

35+
def get_docstring(x):
36+
class_name, method = x.split('.')
37+
obj = getattr(getattr(pd, class_name), method)
38+
return obj.__doc__
39+
40+
def deprecation_version(x):
41+
pattern = re.compile('\.\. deprecated:: ([0-9]+\.[0-9]+\.[0-9]+)')
42+
doc = get_docstring(x)
43+
match = pattern.search(doc)
44+
if match:
45+
return match.groups()[0]
46+
47+
def add_notes(x):
48+
# Some methods are not documented in api.rst because they
49+
# have been deprecated. Adding a comment to detect them easier.
50+
doc = get_docstring(x)
51+
note = None
52+
if not doc:
53+
note = 'no docstring'
54+
else:
55+
version = deprecation_version(x)
56+
if version:
57+
note = 'deprecated in {}'.format(version)
58+
59+
return '{} ({})'.format(x, note) if note else x
60+
1661
# class members
1762
class_members = set()
1863
for cls in classes:
@@ -34,10 +79,12 @@ def class_name_sort_key(x):
3479
print(x)
3580

3681
print()
37-
print("Class members (other than those beginning with '_') missing from api.rst:")
38-
for x in sorted(class_members.difference(api_rst_members), key=class_name_sort_key):
82+
print("Class members (other than those beginning with '_') "
83+
"missing from api.rst:")
84+
for x in sorted(class_members.difference(api_rst_members),
85+
key=class_name_sort_key):
3986
if '._' not in x:
40-
print(x)
87+
print(add_notes(x))
4188

4289
if __name__ == "__main__":
4390
main()

0 commit comments

Comments
 (0)
Please sign in to comment.