From 6be1235a29d62f81f57ccbb7e36a6d8f27fac47c Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 08:34:29 +1000 Subject: [PATCH 01/18] Started work on shared doc idea but noticed get_loc is already forked so will back out and follow that pattern --- pandas/core/indexes/base.py | 40 ++++++++++++++++++++++++--------- pandas/core/indexes/interval.py | 5 ++++- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index eff7ff2c9f347..47b3b4692dbc2 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -2689,7 +2689,7 @@ def _convert_can_do_setop(self, other): # -------------------------------------------------------------------- # Indexing Methods - _index_shared_docs['get_loc'] = """ + _get_loc_template = """ Get integer location, slice or boolean mask for requested label. Parameters @@ -2697,10 +2697,13 @@ def _convert_can_do_setop(self, other): key : label method : {None, 'pad'/'ffill', 'backfill'/'bfill', 'nearest'}, optional * default: exact matches only. - * pad / ffill: find the PREVIOUS index value if no exact match. - * backfill / bfill: use NEXT index value if no exact match + * pad / ffill: find the PREVIOUS index value if no exact + match%(notes)s. + * backfill / bfill: use NEXT index value if no exact + match%(notes)s. * nearest: use the NEAREST index value if no exact match. Tied - distances are broken by preferring the larger index value. + distances are broken by preferring the larger index + value%(notes)s. tolerance : optional Maximum distance from index value for inexact matches. The value of the index at the matching location most satisfy the equation @@ -2732,8 +2735,14 @@ def _convert_can_do_setop(self, other): >>> non_monotonic_index.get_loc('b') array([False, True, False, True], dtype=bool) """ + _index_shared_docs['get_loc_base'] = _get_loc_template % { + 'notes': '', + } + _index_shared_docs['get_loc_interval'] = _get_loc_template % { + 'notes': ' (not yet implemented for IntervalIndex)', + } - @Appender(_index_shared_docs['get_loc']) + @Appender(_index_shared_docs['get_loc_base']) def get_loc(self, key, method=None, tolerance=None): if method is None: if tolerance is not None: @@ -2751,7 +2760,7 @@ def get_loc(self, key, method=None, tolerance=None): raise KeyError(key) return loc - _index_shared_docs['get_indexer'] = """ + _get_indexer_template = """ Compute indexer and mask for new index given the current index. The indexer should be then used as an input to ndarray.take to align the current data to the new index. @@ -2761,10 +2770,13 @@ def get_loc(self, key, method=None, tolerance=None): target : %(target_klass)s method : {None, 'pad'/'ffill', 'backfill'/'bfill', 'nearest'}, optional * default: exact matches only. - * pad / ffill: find the PREVIOUS index value if no exact match. - * backfill / bfill: use NEXT index value if no exact match - * nearest: use the NEAREST index value if no exact match. Tied - distances are broken by preferring the larger index value. + * pad / ffill: find the PREVIOUS index value if no exact + match%(notes)s. + * backfill / bfill: use NEXT index value if no exact + match%(notes)s. + * nearest: use the NEAREST index value if no exact match. + Tied distances are broken by preferring the larger index + value%(notes)s. limit : int, optional Maximum number of consecutive labels in ``target`` to match for inexact matches. @@ -2797,8 +2809,14 @@ def get_loc(self, key, method=None, tolerance=None): Notice that the return value is an array of locations in ``index`` and ``x`` is marked by -1, as it is not in ``index``. """ + _index_shared_docs['get_indexer_base'] = _get_indexer_template % { + 'notes': '', + } + _index_shared_docs['get_indexer_interval'] = _get_indexer_template % { + 'notes': ' (not yet implemented for IntervalIndex)', + } - @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) + @Appender(_index_shared_docs['get_indexer_base'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): method = missing.clean_reindex_fill_method(method) target = ensure_index(target) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 87216dcc7b957..8a8517e48847a 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -648,6 +648,8 @@ def _check_method(self, method): return if method in ['bfill', 'backfill', 'pad', 'ffill', 'nearest']: + # The documentation warns that these methods are not yet implemented + # so it would be worth updating the documentation when fixing. msg = 'method {method} not yet implemented for IntervalIndex' raise NotImplementedError(msg.format(method=method)) @@ -723,6 +725,7 @@ def get_loc(self, key, method=None): key : label method : {None}, optional * default: matches where the label is within an interval only. + * other methods not Returns ------- @@ -805,7 +808,7 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) + @Appender(_index_shared_docs['get_indexer_interval'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): self._check_method(method) From 59182d799d072eb10f75ab2ad12bb8303dcafe45 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 11:47:43 +1000 Subject: [PATCH 02/18] Follow example of forking doc from get_loc method Originally had made a template from the documentation so a common basis could be used with the IntervalIndex adding a warning that the other methods were as yet unsupported. In the end because I am not clear on what effect putting a template in the core documentation dictionary I feel back to just following get_loc and forking the doc string. --- pandas/core/indexes/base.py | 40 ++++++++-------------------- pandas/core/indexes/interval.py | 46 ++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 33 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 47b3b4692dbc2..eff7ff2c9f347 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -2689,7 +2689,7 @@ def _convert_can_do_setop(self, other): # -------------------------------------------------------------------- # Indexing Methods - _get_loc_template = """ + _index_shared_docs['get_loc'] = """ Get integer location, slice or boolean mask for requested label. Parameters @@ -2697,13 +2697,10 @@ def _convert_can_do_setop(self, other): key : label method : {None, 'pad'/'ffill', 'backfill'/'bfill', 'nearest'}, optional * default: exact matches only. - * pad / ffill: find the PREVIOUS index value if no exact - match%(notes)s. - * backfill / bfill: use NEXT index value if no exact - match%(notes)s. + * pad / ffill: find the PREVIOUS index value if no exact match. + * backfill / bfill: use NEXT index value if no exact match * nearest: use the NEAREST index value if no exact match. Tied - distances are broken by preferring the larger index - value%(notes)s. + distances are broken by preferring the larger index value. tolerance : optional Maximum distance from index value for inexact matches. The value of the index at the matching location most satisfy the equation @@ -2735,14 +2732,8 @@ def _convert_can_do_setop(self, other): >>> non_monotonic_index.get_loc('b') array([False, True, False, True], dtype=bool) """ - _index_shared_docs['get_loc_base'] = _get_loc_template % { - 'notes': '', - } - _index_shared_docs['get_loc_interval'] = _get_loc_template % { - 'notes': ' (not yet implemented for IntervalIndex)', - } - @Appender(_index_shared_docs['get_loc_base']) + @Appender(_index_shared_docs['get_loc']) def get_loc(self, key, method=None, tolerance=None): if method is None: if tolerance is not None: @@ -2760,7 +2751,7 @@ def get_loc(self, key, method=None, tolerance=None): raise KeyError(key) return loc - _get_indexer_template = """ + _index_shared_docs['get_indexer'] = """ Compute indexer and mask for new index given the current index. The indexer should be then used as an input to ndarray.take to align the current data to the new index. @@ -2770,13 +2761,10 @@ def get_loc(self, key, method=None, tolerance=None): target : %(target_klass)s method : {None, 'pad'/'ffill', 'backfill'/'bfill', 'nearest'}, optional * default: exact matches only. - * pad / ffill: find the PREVIOUS index value if no exact - match%(notes)s. - * backfill / bfill: use NEXT index value if no exact - match%(notes)s. - * nearest: use the NEAREST index value if no exact match. - Tied distances are broken by preferring the larger index - value%(notes)s. + * pad / ffill: find the PREVIOUS index value if no exact match. + * backfill / bfill: use NEXT index value if no exact match + * nearest: use the NEAREST index value if no exact match. Tied + distances are broken by preferring the larger index value. limit : int, optional Maximum number of consecutive labels in ``target`` to match for inexact matches. @@ -2809,14 +2797,8 @@ def get_loc(self, key, method=None, tolerance=None): Notice that the return value is an array of locations in ``index`` and ``x`` is marked by -1, as it is not in ``index``. """ - _index_shared_docs['get_indexer_base'] = _get_indexer_template % { - 'notes': '', - } - _index_shared_docs['get_indexer_interval'] = _get_indexer_template % { - 'notes': ' (not yet implemented for IntervalIndex)', - } - @Appender(_index_shared_docs['get_indexer_base'] % _index_doc_kwargs) + @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): method = missing.clean_reindex_fill_method(method) target = ensure_index(target) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 8a8517e48847a..a8481e20ac72c 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -648,8 +648,6 @@ def _check_method(self, method): return if method in ['bfill', 'backfill', 'pad', 'ffill', 'nearest']: - # The documentation warns that these methods are not yet implemented - # so it would be worth updating the documentation when fixing. msg = 'method {method} not yet implemented for IntervalIndex' raise NotImplementedError(msg.format(method=method)) @@ -725,7 +723,6 @@ def get_loc(self, key, method=None): key : label method : {None}, optional * default: matches where the label is within an interval only. - * other methods not Returns ------- @@ -808,8 +805,49 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Appender(_index_shared_docs['get_indexer_interval'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): + """ + Compute indexer and mask for new index given the current index. The + indexer should be then used as an input to ndarray.take to align the + current data to the new index. + + Parameters + ---------- + target : %(target_klass)s + method : {None}, optional + * default: exact matches only. + limit : int, optional + Maximum number of consecutive labels in ``target`` to match for + inexact matches. + tolerance : optional + Maximum distance between original and new labels for inexact + matches. The values of the index at the matching locations most + satisfy the equation ``abs(index[indexer] - target) <= tolerance``. + + Tolerance may be a scalar value, which applies the same tolerance + to all values, or list-like, which applies variable tolerance per + element. List-like includes list, tuple, array, Series, and must be + the same size as the index and its dtype must exactly match the + index's type. + + .. versionadded:: 0.21.0 (list-like tolerance) + + Returns + ------- + indexer : ndarray of int + Integers from 0 to n - 1 indicating that the index at these + positions matches the corresponding target values. Missing values + in the target are marked by -1. + + Examples + -------- + >>> index = pd.Index(['c', 'a', 'b']) + >>> index.get_indexer(['a', 'b', 'x']) + array([ 1, 2, -1]) + + Notice that the return value is an array of locations in ``index`` + and ``x`` is marked by -1, as it is not in ``index``. + """ self._check_method(method) target = ensure_index(target) From b7fc1bddf8555f24a0d8bfb821cae694213019ff Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 11:51:20 +1000 Subject: [PATCH 03/18] Add back in note to adjust the doc string if fixing the implementation --- pandas/core/indexes/interval.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index a8481e20ac72c..6eff8843064fc 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -648,6 +648,8 @@ def _check_method(self, method): return if method in ['bfill', 'backfill', 'pad', 'ffill', 'nearest']: + # The documentation warns these methods are not implemented so if + # this is fixed please fix the doc string. msg = 'method {method} not yet implemented for IntervalIndex' raise NotImplementedError(msg.format(method=method)) From 9b9436f900d2346eeaef31540e2d6609a88a39a2 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 12:48:42 +1000 Subject: [PATCH 04/18] Use docstring substitution instead Following the notes in the contributors guide - have opted for using docstring substition (https://pandas-docs.github.io/pandas-docs-travis/development/contributing_docstring.html#sharing-docstrings). --- pandas/core/indexes/base.py | 11 +++++--- pandas/core/indexes/interval.py | 48 ++++----------------------------- 2 files changed, 13 insertions(+), 46 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index eff7ff2c9f347..dcdbde3fb84f2 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -2761,10 +2761,13 @@ def get_loc(self, key, method=None, tolerance=None): target : %(target_klass)s method : {None, 'pad'/'ffill', 'backfill'/'bfill', 'nearest'}, optional * default: exact matches only. - * pad / ffill: find the PREVIOUS index value if no exact match. - * backfill / bfill: use NEXT index value if no exact match + * pad / ffill: find the PREVIOUS index value if no exact + match%(method_param_pad_notes)s. + * backfill / bfill: use NEXT index value if no exact + match%(method_param_backfill_notes)s. * nearest: use the NEAREST index value if no exact match. Tied - distances are broken by preferring the larger index value. + distances are broken by preferring the larger index + value%(method_param_nearest_notes)s. limit : int, optional Maximum number of consecutive labels in ``target`` to match for inexact matches. @@ -2798,6 +2801,8 @@ def get_loc(self, key, method=None, tolerance=None): and ``x`` is marked by -1, as it is not in ``index``. """ + @Substitution(method_param_pad_notes='', method_param_backfill_notes='', + method_param_nearest_notes='') @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): method = missing.clean_reindex_fill_method(method) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 6eff8843064fc..fb74c3db93a4c 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -8,7 +8,7 @@ from pandas._libs import Timedelta, Timestamp from pandas._libs.interval import Interval, IntervalMixin, IntervalTree -from pandas.util._decorators import Appender, cache_readonly +from pandas.util._decorators import Appender, Substitution, cache_readonly from pandas.util._exceptions import rewrite_exception from pandas.core.dtypes.cast import ( @@ -807,49 +807,11 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] + @Substitution(method_param_pad_notes=' (not yet supported).', + method_param_backfill_notes=' (not yet supported).', + method_param_nearest_notes=' (not yet supported).') + @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): - """ - Compute indexer and mask for new index given the current index. The - indexer should be then used as an input to ndarray.take to align the - current data to the new index. - - Parameters - ---------- - target : %(target_klass)s - method : {None}, optional - * default: exact matches only. - limit : int, optional - Maximum number of consecutive labels in ``target`` to match for - inexact matches. - tolerance : optional - Maximum distance between original and new labels for inexact - matches. The values of the index at the matching locations most - satisfy the equation ``abs(index[indexer] - target) <= tolerance``. - - Tolerance may be a scalar value, which applies the same tolerance - to all values, or list-like, which applies variable tolerance per - element. List-like includes list, tuple, array, Series, and must be - the same size as the index and its dtype must exactly match the - index's type. - - .. versionadded:: 0.21.0 (list-like tolerance) - - Returns - ------- - indexer : ndarray of int - Integers from 0 to n - 1 indicating that the index at these - positions matches the corresponding target values. Missing values - in the target are marked by -1. - - Examples - -------- - >>> index = pd.Index(['c', 'a', 'b']) - >>> index.get_indexer(['a', 'b', 'x']) - array([ 1, 2, -1]) - - Notice that the return value is an array of locations in ``index`` - and ``x`` is marked by -1, as it is not in ``index``. - """ self._check_method(method) target = ensure_index(target) From 17771204f9bdab13cafd8660cf87dc43f89a214f Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 12:52:12 +1000 Subject: [PATCH 05/18] Remove double full-stop --- pandas/core/indexes/interval.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index fb74c3db93a4c..5523d610301d7 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -807,9 +807,9 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Substitution(method_param_pad_notes=' (not yet supported).', - method_param_backfill_notes=' (not yet supported).', - method_param_nearest_notes=' (not yet supported).') + @Substitution(method_param_pad_notes=' (not yet supported)', + method_param_backfill_notes=' (not yet supported)', + method_param_nearest_notes=' (not yet supported)') @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): From 7f06fbd9c2232c459b79fcea4928dd95bfa2ba3d Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 13:33:25 +1000 Subject: [PATCH 06/18] Looks like this section has its own substition technique --- pandas/core/indexes/base.py | 5 +++-- pandas/core/indexes/interval.py | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index dcdbde3fb84f2..fe2544b85af07 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -52,6 +52,9 @@ _index_doc_kwargs = dict(klass='Index', inplace='', target_klass='Index', + method_param_pad_notes='', + method_param_backfill_notes='', + method_param_nearest_notes='', unique='Index', duplicated='np.ndarray') _index_shared_docs = dict() @@ -2801,8 +2804,6 @@ def get_loc(self, key, method=None, tolerance=None): and ``x`` is marked by -1, as it is not in ``index``. """ - @Substitution(method_param_pad_notes='', method_param_backfill_notes='', - method_param_nearest_notes='') @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): method = missing.clean_reindex_fill_method(method) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 5523d610301d7..7bde47d1df34c 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -39,6 +39,9 @@ dict(klass='IntervalIndex', qualname="IntervalIndex", target_klass='IntervalIndex or list of Intervals', + method_param_pad_notes=' (not yet supported)', + method_param_backfill_notes=' (not yet supported)', + method_param_nearest_notes=' (not yet supported)', name=textwrap.dedent("""\ name : object, optional Name to be stored in the index. @@ -807,9 +810,6 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Substitution(method_param_pad_notes=' (not yet supported)', - method_param_backfill_notes=' (not yet supported)', - method_param_nearest_notes=' (not yet supported)') @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): From 810ec5a5dfc4f929376f34331c0247efd8fadd60 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 13:35:15 +1000 Subject: [PATCH 07/18] Drop unused import --- pandas/core/indexes/interval.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 7bde47d1df34c..01b72887ee0f0 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -8,7 +8,7 @@ from pandas._libs import Timedelta, Timestamp from pandas._libs.interval import Interval, IntervalMixin, IntervalTree -from pandas.util._decorators import Appender, Substitution, cache_readonly +from pandas.util._decorators import Appender, cache_readonly from pandas.util._exceptions import rewrite_exception from pandas.core.dtypes.cast import ( From 0ad7c8cb6fddf98fbadd9c74f98e081db33ba62e Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 26 May 2019 19:55:44 +1000 Subject: [PATCH 08/18] Restore original --- pandas/core/indexes/base.py | 12 +++--------- pandas/core/indexes/interval.py | 5 ----- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index fe2544b85af07..eff7ff2c9f347 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -52,9 +52,6 @@ _index_doc_kwargs = dict(klass='Index', inplace='', target_klass='Index', - method_param_pad_notes='', - method_param_backfill_notes='', - method_param_nearest_notes='', unique='Index', duplicated='np.ndarray') _index_shared_docs = dict() @@ -2764,13 +2761,10 @@ def get_loc(self, key, method=None, tolerance=None): target : %(target_klass)s method : {None, 'pad'/'ffill', 'backfill'/'bfill', 'nearest'}, optional * default: exact matches only. - * pad / ffill: find the PREVIOUS index value if no exact - match%(method_param_pad_notes)s. - * backfill / bfill: use NEXT index value if no exact - match%(method_param_backfill_notes)s. + * pad / ffill: find the PREVIOUS index value if no exact match. + * backfill / bfill: use NEXT index value if no exact match * nearest: use the NEAREST index value if no exact match. Tied - distances are broken by preferring the larger index - value%(method_param_nearest_notes)s. + distances are broken by preferring the larger index value. limit : int, optional Maximum number of consecutive labels in ``target`` to match for inexact matches. diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 01b72887ee0f0..87216dcc7b957 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -39,9 +39,6 @@ dict(klass='IntervalIndex', qualname="IntervalIndex", target_klass='IntervalIndex or list of Intervals', - method_param_pad_notes=' (not yet supported)', - method_param_backfill_notes=' (not yet supported)', - method_param_nearest_notes=' (not yet supported)', name=textwrap.dedent("""\ name : object, optional Name to be stored in the index. @@ -651,8 +648,6 @@ def _check_method(self, method): return if method in ['bfill', 'backfill', 'pad', 'ffill', 'nearest']: - # The documentation warns these methods are not implemented so if - # this is fixed please fix the doc string. msg = 'method {method} not yet implemented for IntervalIndex' raise NotImplementedError(msg.format(method=method)) From f6331e45cef5cdf2be22be832a88de557b126093 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 25 May 2019 11:51:20 +1000 Subject: [PATCH 09/18] Add back in note to adjust the doc string if fixing the implementation --- pandas/core/indexes/interval.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 87216dcc7b957..9c43ef7c7555b 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -648,6 +648,8 @@ def _check_method(self, method): return if method in ['bfill', 'backfill', 'pad', 'ffill', 'nearest']: + # The documentation warns these methods are not implemented so if + # this is fixed please fix the doc string. msg = 'method {method} not yet implemented for IntervalIndex' raise NotImplementedError(msg.format(method=method)) From 3f83d82503b794079c749e5ee70bf57716cb47f6 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 26 May 2019 20:03:27 +1000 Subject: [PATCH 10/18] Use Appender raises to notify of the deficiency As suggested by @WillAyd instead of altering the docstring using a global substitution just append a raises docstring section that warns about the parts not yet implemented. --- pandas/core/indexes/interval.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 9c43ef7c7555b..5cd20fb283712 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -807,6 +807,12 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] + @Appender(textwrap.dedent(""" + Raises + ------ + raises NotImplementedError if any method other than than the default + method is specified as these are not yet implemented. + """)) @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) def get_indexer(self, target, method=None, limit=None, tolerance=None): From 88f59c318648a30d1f45caf935c0d876f09630b1 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 26 May 2019 21:14:42 +1000 Subject: [PATCH 11/18] Resolve check_doc failure Raises section must appear before Examples which complicates the use of just appending a doc section and instead must perform a substitution. --- pandas/core/indexes/base.py | 3 ++- pandas/core/indexes/interval.py | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index eff7ff2c9f347..59f5e256b475f 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -52,6 +52,7 @@ _index_doc_kwargs = dict(klass='Index', inplace='', target_klass='Index', + raises_section='', unique='Index', duplicated='np.ndarray') _index_shared_docs = dict() @@ -2788,7 +2789,7 @@ def get_loc(self, key, method=None, tolerance=None): positions matches the corresponding target values. Missing values in the target are marked by -1. - Examples + %(raises_section)sExamples -------- >>> index = pd.Index(['c', 'a', 'b']) >>> index.get_indexer(['a', 'b', 'x']) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 5cd20fb283712..0b8e5ba7d2b4e 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -8,7 +8,7 @@ from pandas._libs import Timedelta, Timestamp from pandas._libs.interval import Interval, IntervalMixin, IntervalTree -from pandas.util._decorators import Appender, cache_readonly +from pandas.util._decorators import Appender, Substitution, cache_readonly from pandas.util._exceptions import rewrite_exception from pandas.core.dtypes.cast import ( @@ -807,13 +807,14 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Appender(textwrap.dedent(""" + @Substitution(dict(_index_doc_kwargs, **{'raises_section': textwrap.dedent("""\ Raises ------ raises NotImplementedError if any method other than than the default method is specified as these are not yet implemented. - """)) - @Appender(_index_shared_docs['get_indexer'] % _index_doc_kwargs) + + """)})) + @Appender(_index_shared_docs['get_indexer']) def get_indexer(self, target, method=None, limit=None, tolerance=None): self._check_method(method) From dd6a18ed5145e8af2d8e2937b37a950f6ccb3896 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 26 May 2019 21:21:53 +1000 Subject: [PATCH 12/18] Satisfy flake8 overflow and line length Avoid exceeding column count and maintain flake8 line overflow requirements --- pandas/core/indexes/interval.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 0b8e5ba7d2b4e..b4964fe95cb30 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -807,7 +807,8 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Substitution(dict(_index_doc_kwargs, **{'raises_section': textwrap.dedent("""\ + @Substitution(dict(_index_doc_kwargs, + **{'raises_section': textwrap.dedent("""\ Raises ------ raises NotImplementedError if any method other than than the default From a3fc35a6add3dbf68a055ce3442df18bea2f7818 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 26 May 2019 22:10:42 +1000 Subject: [PATCH 13/18] Use correct raises syntax - Thanks @TomAugspurger --- pandas/core/indexes/interval.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index b4964fe95cb30..2b7522d539546 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -811,8 +811,9 @@ def get_value(self, series, key): **{'raises_section': textwrap.dedent("""\ Raises ------ - raises NotImplementedError if any method other than than the default - method is specified as these are not yet implemented. + NotImplementedError + If any method other than than the default method is specified as + these are not yet implemented. """)})) @Appender(_index_shared_docs['get_indexer']) From c420a42223f3ffe32007c0591dd3633fb856a337 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 26 May 2019 22:17:15 +1000 Subject: [PATCH 14/18] Substitution uses kwargs for dict formats. If you supply an argument then it assumes the substitution is a straight sequence for the string format as it uses args or kwargs. --- pandas/core/indexes/interval.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 2b7522d539546..3e42f06b190b4 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -807,8 +807,8 @@ def get_value(self, series, key): loc = self.get_loc(key) return series.iloc[loc] - @Substitution(dict(_index_doc_kwargs, - **{'raises_section': textwrap.dedent("""\ + @Substitution(**dict(_index_doc_kwargs, + **{'raises_section': textwrap.dedent("""\ Raises ------ NotImplementedError From cd71f2cf675aac84e34e1ae4ddde77c198ae87be Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Mon, 27 May 2019 05:52:01 +1000 Subject: [PATCH 15/18] Drop comment as requested by @jreback --- pandas/core/indexes/interval.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 3e42f06b190b4..9d2bd617ace6b 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -648,8 +648,6 @@ def _check_method(self, method): return if method in ['bfill', 'backfill', 'pad', 'ffill', 'nearest']: - # The documentation warns these methods are not implemented so if - # this is fixed please fix the doc string. msg = 'method {method} not yet implemented for IntervalIndex' raise NotImplementedError(msg.format(method=method)) From 4bbcbd128caf9f193d089cd85808d7a8896838ae Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Mon, 27 May 2019 05:53:36 +1000 Subject: [PATCH 16/18] Cleaner look as suggested by @jreback If we remove the line at the end when substituting in the raises section and add one at the start then in the template the raises_section substitution can be on its own line which is a cleaner solution - thanks to @jreback. --- pandas/core/indexes/base.py | 4 ++-- pandas/core/indexes/interval.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 59f5e256b475f..caf881ef069e6 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -2788,8 +2788,8 @@ def get_loc(self, key, method=None, tolerance=None): Integers from 0 to n - 1 indicating that the index at these positions matches the corresponding target values. Missing values in the target are marked by -1. - - %(raises_section)sExamples + %(raises_section)s + Examples -------- >>> index = pd.Index(['c', 'a', 'b']) >>> index.get_indexer(['a', 'b', 'x']) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 9d2bd617ace6b..ff45a341e2c94 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -806,13 +806,12 @@ def get_value(self, series, key): return series.iloc[loc] @Substitution(**dict(_index_doc_kwargs, - **{'raises_section': textwrap.dedent("""\ + **{'raises_section': textwrap.dedent(""" Raises ------ NotImplementedError If any method other than than the default method is specified as these are not yet implemented. - """)})) @Appender(_index_shared_docs['get_indexer']) def get_indexer(self, target, method=None, limit=None, tolerance=None): From 11e8a764d300be4fb56f59e06534e5a3e9dd63bb Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Wed, 29 May 2019 08:37:13 +1000 Subject: [PATCH 17/18] Fix up use incorrect sentence that had a double "than" in it. --- pandas/core/indexes/interval.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index ff45a341e2c94..2de7f7831af71 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -809,9 +809,8 @@ def get_value(self, series, key): **{'raises_section': textwrap.dedent(""" Raises ------ - NotImplementedError - If any method other than than the default method is specified as - these are not yet implemented. + NotImplementedError: If any method argument other than the default of + None is specified as these are not yet implemented. """)})) @Appender(_index_shared_docs['get_indexer']) def get_indexer(self, target, method=None, limit=None, tolerance=None): From ae7470c1c256f980b11e74cda78194f84e9f679f Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Wed, 29 May 2019 08:40:06 +1000 Subject: [PATCH 18/18] Fix layout to match expected raises syntax --- pandas/core/indexes/interval.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/indexes/interval.py b/pandas/core/indexes/interval.py index 2de7f7831af71..a3b162a91ed19 100644 --- a/pandas/core/indexes/interval.py +++ b/pandas/core/indexes/interval.py @@ -809,7 +809,8 @@ def get_value(self, series, key): **{'raises_section': textwrap.dedent(""" Raises ------ - NotImplementedError: If any method argument other than the default of + NotImplementedError + If any method argument other than the default of None is specified as these are not yet implemented. """)})) @Appender(_index_shared_docs['get_indexer'])