From ac1ca248406d227bcc9e729903e0a98414be2dcc Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Sun, 19 Aug 2018 19:34:20 +0100 Subject: [PATCH 1/9] BUG: Ignore versionadded directive when checking for periods at docstring end --- scripts/validate_docstrings.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index cdea2d8b83abd..fba9cfa8213dd 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -465,7 +465,15 @@ def validate_one(func_name): param_errs.append('Parameter "{}" description ' 'should start with a ' 'capital letter'.format(param)) - if doc.parameter_desc(param)[-1] != '.': + + if '.. versionadded::' in doc.parameter_desc(param): + index = doc.parameter_desc(param).index('.. versionadded::') + # Check for periods at the end of the description before the + # versionadded directive + period_check_index = index - 1 + else: + period_check_index = -1 + if doc.parameter_desc(param)[period_check_index] != '.': param_errs.append('Parameter "{}" description ' 'should finish with "."'.format(param)) if param_errs: From b06cdbf5d9c3a0c388364a46eda61e303437fc8d Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Sun, 19 Aug 2018 20:36:52 +0100 Subject: [PATCH 2/9] TST: Added test cases for versionadded directive --- .../tests/scripts/test_validate_docstrings.py | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/pandas/tests/scripts/test_validate_docstrings.py b/pandas/tests/scripts/test_validate_docstrings.py index 1d35d5d30bba3..fb4ac1c002ead 100644 --- a/pandas/tests/scripts/test_validate_docstrings.py +++ b/pandas/tests/scripts/test_validate_docstrings.py @@ -193,6 +193,44 @@ def contains(self, pat, case=True, na=np.nan): """ pass + def mode(self, axis=0, numeric_only=False, dropna=True): + """ + Get the mode(s) of each element along the axis selected. Adds a row + for each mode per label, fills in gaps with nan. + + Note that there could be multiple values returned for the selected + axis (when more than one item share the maximum frequency), which is + the reason why a dataframe is returned. If you want to impute missing + values with the mode in a dataframe ``df``, you can just do this: + ``df.fillna(df.mode().iloc[0])`` + + Parameters + ---------- + axis : {0 or 'index', 1 or 'columns'}, default 0 + Describe axis. + numeric_only : boolean, default False + Describes numeric_only. + dropna : boolean, default True + This param tests that the versionadded directive doesn't break the + checks for the ending period. + Don't consider counts of NaN/NaT. + + .. versionadded:: 0.24.0 + + Returns + ------- + modes : DataFrame (sorted) + + Examples + -------- + >>> df = pd.DataFrame({'A': [1, 2, 1, 2, 1, 2, 3]}) + >>> df.mode() + A + 0 1 + 1 2 + """ + pass + class BadGenericDocStrings(object): """Everything here has a bad docstring @@ -374,6 +412,18 @@ def no_description_period(self, kind): Doesn't end with a dot """ + def no_description_period_with_version_added(self, kind): + """ + Forgets to add a period, and also includes a directive. + + Parameters + ---------- + kind : str + Doesn't end with a dot + + .. versionadded:: 0.00.0 + """ + def parameter_capitalization(self, kind): """ Forgets to capitalize the description. @@ -495,7 +545,7 @@ def test_good_class(self): @pytest.mark.parametrize("func", [ 'plot', 'sample', 'random_letters', 'sample_values', 'head', 'head1', - 'contains']) + 'contains', 'mode']) def test_good_functions(self, func): assert validate_one(self._import_path( # noqa: F821 klass='GoodDocStrings', func=func)) == 0 @@ -531,6 +581,8 @@ def test_bad_generic_functions(self, func): 'Parameter "kind: str" has no type')), ('BadParameters', 'no_description_period', ('Parameter "kind" description should finish with "."',)), + ('BadParameters', 'no_description_period_with_version_added', + ('Parameter "kind" description should finish with "."',)), ('BadParameters', 'parameter_capitalization', ('Parameter "kind" description should start with a capital letter',)), pytest.param('BadParameters', 'blank_lines', ('No error yet?',), From 25382b9bbabf1e1590cb872bb9ceedd1468e2e1f Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Sun, 19 Aug 2018 21:20:10 +0100 Subject: [PATCH 3/9] BUG: Refactor to ignore versionchanged and deprecated directives. --- scripts/validate_docstrings.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index fba9cfa8213dd..fe3c1fa58e461 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -42,6 +42,7 @@ PRIVATE_CLASSES = ['NDFrame', 'IndexOpsMixin'] +DIRECTIVES = ['.. versionadded', '.. versionchanged', '.. deprecated'] def _load_obj(obj_name): @@ -466,13 +467,15 @@ def validate_one(func_name): 'should start with a ' 'capital letter'.format(param)) - if '.. versionadded::' in doc.parameter_desc(param): - index = doc.parameter_desc(param).index('.. versionadded::') - # Check for periods at the end of the description before the - # versionadded directive - period_check_index = index - 1 - else: - period_check_index = -1 + period_check_index = -1 + for directive in DIRECTIVES: + if directive in doc.parameter_desc(param): + # Get index of character before start of directive + index = doc.parameter_desc(param).index(directive) - 1 + # If this directive is closest to the description, use it. + if index < period_check_index or period_check_index is -1: + period_check_index = index + if doc.parameter_desc(param)[period_check_index] != '.': param_errs.append('Parameter "{}" description ' 'should finish with "."'.format(param)) From cd861fec943d6769218f30894aaf819242b8111c Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Sun, 19 Aug 2018 21:27:42 +0100 Subject: [PATCH 4/9] TST: Add multiple directives to tests --- .../tests/scripts/test_validate_docstrings.py | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/pandas/tests/scripts/test_validate_docstrings.py b/pandas/tests/scripts/test_validate_docstrings.py index fb4ac1c002ead..e4f7d776aa713 100644 --- a/pandas/tests/scripts/test_validate_docstrings.py +++ b/pandas/tests/scripts/test_validate_docstrings.py @@ -198,6 +198,8 @@ def mode(self, axis=0, numeric_only=False, dropna=True): Get the mode(s) of each element along the axis selected. Adds a row for each mode per label, fills in gaps with nan. + This test is to ensure that directives don't affect the tests for + periods at the end of parameters. Note that there could be multiple values returned for the selected axis (when more than one item share the maximum frequency), which is the reason why a dataframe is returned. If you want to impute missing @@ -208,8 +210,15 @@ def mode(self, axis=0, numeric_only=False, dropna=True): ---------- axis : {0 or 'index', 1 or 'columns'}, default 0 Describe axis. + + .. versionchanged:: 0.1.2 + numeric_only : boolean, default False Describes numeric_only. + + .. versionadded:: 0.1.2 + .. deprecated:: 0.00.0 + dropna : boolean, default True This param tests that the versionadded directive doesn't break the checks for the ending period. @@ -412,7 +421,7 @@ def no_description_period(self, kind): Doesn't end with a dot """ - def no_description_period_with_version_added(self, kind): + def no_description_period_with_directive(self, kind): """ Forgets to add a period, and also includes a directive. @@ -424,6 +433,19 @@ def no_description_period_with_version_added(self, kind): .. versionadded:: 0.00.0 """ + def no_description_period_with_directives(self, kind): + """ + Forgets to add a period, and also includes multiple directives. + + Parameters + ---------- + kind : str + Doesn't end with a dot + + .. versionchanged:: 0.00.0 + .. deprecated:: 0.00.0 + """ + def parameter_capitalization(self, kind): """ Forgets to capitalize the description. @@ -581,7 +603,7 @@ def test_bad_generic_functions(self, func): 'Parameter "kind: str" has no type')), ('BadParameters', 'no_description_period', ('Parameter "kind" description should finish with "."',)), - ('BadParameters', 'no_description_period_with_version_added', + ('BadParameters', 'no_description_period_with_directive', ('Parameter "kind" description should finish with "."',)), ('BadParameters', 'parameter_capitalization', ('Parameter "kind" description should start with a capital letter',)), From cb4bcc367d539e36cde6d3bc3d75be65adf04405 Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Mon, 20 Aug 2018 19:42:51 +0100 Subject: [PATCH 5/9] CLN: Add property for parameter descriptions excluding directives --- scripts/validate_docstrings.py | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index fe3c1fa58e461..8dfa5cc9a6ca3 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -42,7 +42,7 @@ PRIVATE_CLASSES = ['NDFrame', 'IndexOpsMixin'] -DIRECTIVES = ['.. versionadded', '.. versionchanged', '.. deprecated'] +DIRECTIVES = ['versionadded', 'versionchanged', 'deprecated'] def _load_obj(obj_name): @@ -237,6 +237,15 @@ def parameter_type(self, param): def parameter_desc(self, param): return self.doc_parameters[param][1] + def parameter_desc_without_directives(self, param): + desc = self.parameter_desc(param) + for directive in DIRECTIVES: + full_directive = '.. {}'.format(directive) + if full_directive in desc: + # Only retain any description before the directive + desc = desc[:desc.index(full_directive)] + return desc + @property def see_also(self): return collections.OrderedDict((name, ''.join(desc)) @@ -466,17 +475,7 @@ def validate_one(func_name): param_errs.append('Parameter "{}" description ' 'should start with a ' 'capital letter'.format(param)) - - period_check_index = -1 - for directive in DIRECTIVES: - if directive in doc.parameter_desc(param): - # Get index of character before start of directive - index = doc.parameter_desc(param).index(directive) - 1 - # If this directive is closest to the description, use it. - if index < period_check_index or period_check_index is -1: - period_check_index = index - - if doc.parameter_desc(param)[period_check_index] != '.': + if doc.parameter_desc_without_directives(param)[-1] != '.': param_errs.append('Parameter "{}" description ' 'should finish with "."'.format(param)) if param_errs: From 748b167fa988edfda7fdf7bd629288237adbcde3 Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Mon, 20 Aug 2018 19:45:18 +0100 Subject: [PATCH 6/9] TST: Update test cases for ignoring directives to be more concise. --- .../tests/scripts/test_validate_docstrings.py | 40 +++---------------- 1 file changed, 6 insertions(+), 34 deletions(-) diff --git a/pandas/tests/scripts/test_validate_docstrings.py b/pandas/tests/scripts/test_validate_docstrings.py index e4f7d776aa713..d26858565899d 100644 --- a/pandas/tests/scripts/test_validate_docstrings.py +++ b/pandas/tests/scripts/test_validate_docstrings.py @@ -193,50 +193,22 @@ def contains(self, pat, case=True, na=np.nan): """ pass - def mode(self, axis=0, numeric_only=False, dropna=True): + def mode(self, axis, numeric_only): """ - Get the mode(s) of each element along the axis selected. Adds a row - for each mode per label, fills in gaps with nan. - - This test is to ensure that directives don't affect the tests for - periods at the end of parameters. - Note that there could be multiple values returned for the selected - axis (when more than one item share the maximum frequency), which is - the reason why a dataframe is returned. If you want to impute missing - values with the mode in a dataframe ``df``, you can just do this: - ``df.fillna(df.mode().iloc[0])`` + Ensure sphinx directives don't affect checks for trailing periods. Parameters ---------- - axis : {0 or 'index', 1 or 'columns'}, default 0 - Describe axis. + axis : str + Sentence ending in period, followed by single directive. .. versionchanged:: 0.1.2 - numeric_only : boolean, default False - Describes numeric_only. + numeric_only : boolean + Sentence ending in period, followed by multiple directives. .. versionadded:: 0.1.2 .. deprecated:: 0.00.0 - - dropna : boolean, default True - This param tests that the versionadded directive doesn't break the - checks for the ending period. - Don't consider counts of NaN/NaT. - - .. versionadded:: 0.24.0 - - Returns - ------- - modes : DataFrame (sorted) - - Examples - -------- - >>> df = pd.DataFrame({'A': [1, 2, 1, 2, 1, 2, 3]}) - >>> df.mode() - A - 0 1 - 1 2 """ pass From 37da2cc557be8878163f7543f18a7aa657113120 Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Tue, 21 Aug 2018 22:04:15 +0100 Subject: [PATCH 7/9] CLN: Change parameter_desc to strip out directives --- scripts/validate_docstrings.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 8dfa5cc9a6ca3..03f5b3c350103 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -234,11 +234,12 @@ def correct_parameters(self): def parameter_type(self, param): return self.doc_parameters[param][0] - def parameter_desc(self, param): + def raw_parameter_desc(self, param): return self.doc_parameters[param][1] - def parameter_desc_without_directives(self, param): - desc = self.parameter_desc(param) + def parameter_desc(self, param): + desc = self.raw_parameter_desc(param) + # Find and strip out any sphinx directives for directive in DIRECTIVES: full_directive = '.. {}'.format(directive) if full_directive in desc: @@ -475,7 +476,7 @@ def validate_one(func_name): param_errs.append('Parameter "{}" description ' 'should start with a ' 'capital letter'.format(param)) - if doc.parameter_desc_without_directives(param)[-1] != '.': + if doc.parameter_desc(param)[-1] != '.': param_errs.append('Parameter "{}" description ' 'should finish with "."'.format(param)) if param_errs: From ccfa4d6e24c8fb512ae70a327212c6d819bd1e3c Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Wed, 22 Aug 2018 18:28:38 +0100 Subject: [PATCH 8/9] CLN: Remove raw_parameter_desc as it currently serves no purpose --- scripts/validate_docstrings.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 03f5b3c350103..83bb382480eaa 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -234,11 +234,8 @@ def correct_parameters(self): def parameter_type(self, param): return self.doc_parameters[param][0] - def raw_parameter_desc(self, param): - return self.doc_parameters[param][1] - def parameter_desc(self, param): - desc = self.raw_parameter_desc(param) + desc = self.doc_parameters[param][1] # Find and strip out any sphinx directives for directive in DIRECTIVES: full_directive = '.. {}'.format(directive) From 3039d78adb395c8cc62fcf8cbe325cc7c1e7185b Mon Sep 17 00:00:00 2001 From: bengineer19 Date: Wed, 22 Aug 2018 20:11:23 +0100 Subject: [PATCH 9/9] TST: Test directive descriptions --- pandas/tests/scripts/test_validate_docstrings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/tests/scripts/test_validate_docstrings.py b/pandas/tests/scripts/test_validate_docstrings.py index d26858565899d..8156db6902e20 100644 --- a/pandas/tests/scripts/test_validate_docstrings.py +++ b/pandas/tests/scripts/test_validate_docstrings.py @@ -209,6 +209,8 @@ def mode(self, axis, numeric_only): .. versionadded:: 0.1.2 .. deprecated:: 0.00.0 + A multiline description, + which spans another line. """ pass