From e1f360626bc15fe462d6bffc7c50829104323cc9 Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Sun, 28 Jul 2019 12:41:21 +0200 Subject: [PATCH 1/8] Validate docstring directives Fix #27629 --- scripts/validate_docstrings.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 37623d32db685..0d567cec78285 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -93,6 +93,7 @@ "GL07": "Sections are in the wrong order. Correct order is: " "{correct_sections}", "GL08": "The object does not have a docstring", "GL09": "Deprecation warning should precede extended summary", + "GL10": "reST directives {directives} must be followed by two colons", "SS01": "No summary found (a short summary in a single line should be " "present at the beginning of the docstring)", "SS02": "Summary does not start with a capital letter", @@ -239,6 +240,10 @@ def get_api_items(api_doc_fd): class Docstring: + DIRECTIVES = ['deprecated', 'versionadded', 'versionchanged'] + DIRECTIVE_WITHOUT_TWO_COLONS = re.compile( + rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M) + def __init__(self, name): self.name = name obj = self._load_obj(name) @@ -478,6 +483,10 @@ def parameter_mismatches(self): def correct_parameters(self): return not bool(self.parameter_mismatches) + @property + def directives_without_two_colons(self): + return Docstring.DIRECTIVE_WITHOUT_TWO_COLONS.findall(self.raw_doc) + def parameter_type(self, param): return self.doc_parameters[param][0] @@ -697,6 +706,10 @@ def get_validation_data(doc): if doc.deprecated and not doc.extended_summary.startswith(".. deprecated:: "): errs.append(error("GL09")) + directives_without_two_colons = doc.directives_without_two_colons + if directives_without_two_colons: + errs.append(error("GL10", directives=directives_without_two_colons)) + if not doc.summary: errs.append(error("SS01")) else: From 58929046a9123d8555503141097a664628c0c96d Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Sun, 28 Jul 2019 19:01:42 +0200 Subject: [PATCH 2/8] Fix linting --- scripts/validate_docstrings.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 0d567cec78285..8221f500b3135 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -240,9 +240,10 @@ def get_api_items(api_doc_fd): class Docstring: - DIRECTIVES = ['deprecated', 'versionadded', 'versionchanged'] + DIRECTIVES = ["deprecated", "versionadded", "versionchanged"] DIRECTIVE_WITHOUT_TWO_COLONS = re.compile( - rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M) + rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M + ) def __init__(self, name): self.name = name From ae3f03d0e76d42e90177006a73d239c5644232d9 Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Mon, 5 Aug 2019 22:28:34 +0200 Subject: [PATCH 3/8] Remove duplicated DIRECTIVES --- scripts/validate_docstrings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 8221f500b3135..b943437bc0f1a 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -240,7 +240,6 @@ def get_api_items(api_doc_fd): class Docstring: - DIRECTIVES = ["deprecated", "versionadded", "versionchanged"] DIRECTIVE_WITHOUT_TWO_COLONS = re.compile( rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M ) From caed8d9427a84d284f289e1623205daee9a089ff Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Mon, 5 Aug 2019 22:29:09 +0200 Subject: [PATCH 4/8] Rename regex DIRECTIVE_PATTERN --- scripts/validate_docstrings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index b943437bc0f1a..5bb78ef3a9b1d 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -59,6 +59,9 @@ PRIVATE_CLASSES = ["NDFrame", "IndexOpsMixin"] DIRECTIVES = ["versionadded", "versionchanged", "deprecated"] +DIRECTIVE_PATTERN = re.compile( + rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M +) ALLOWED_SECTIONS = [ "Parameters", "Attributes", @@ -240,9 +243,6 @@ def get_api_items(api_doc_fd): class Docstring: - DIRECTIVE_WITHOUT_TWO_COLONS = re.compile( - rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M - ) def __init__(self, name): self.name = name @@ -485,7 +485,7 @@ def correct_parameters(self): @property def directives_without_two_colons(self): - return Docstring.DIRECTIVE_WITHOUT_TWO_COLONS.findall(self.raw_doc) + return DIRECTIVE_PATTERN.findall(self.raw_doc) def parameter_type(self, param): return self.doc_parameters[param][0] From 11627353a63623a0deb335dd8ed5d00d8d6a697f Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Mon, 5 Aug 2019 22:33:23 +0200 Subject: [PATCH 5/8] Add GL10 to code_checks --- ci/code_checks.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/code_checks.sh b/ci/code_checks.sh index 06d45e38bfcdb..333136ddfddd9 100755 --- a/ci/code_checks.sh +++ b/ci/code_checks.sh @@ -263,8 +263,8 @@ fi ### DOCSTRINGS ### if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then - MSG='Validate docstrings (GL03, GL04, GL05, GL06, GL07, GL09, SS04, SS05, PR03, PR04, PR05, PR10, EX04, RT01, RT04, RT05, SA05)' ; echo $MSG - $BASE_DIR/scripts/validate_docstrings.py --format=azure --errors=GL03,GL04,GL05,GL06,GL07,GL09,SS04,SS05,PR03,PR04,PR05,PR10,EX04,RT01,RT04,RT05,SA05 + MSG='Validate docstrings (GL03, GL04, GL05, GL06, GL07, GL09, GL10, SS04, SS05, PR03, PR04, PR05, PR10, EX04, RT01, RT04, RT05, SA05)' ; echo $MSG + $BASE_DIR/scripts/validate_docstrings.py --format=azure --errors=GL03,GL04,GL05,GL06,GL07,GL09,GL10,SS04,SS05,PR03,PR04,PR05,PR10,EX04,RT01,RT04,RT05,SA05 RET=$(($RET + $?)) ; echo $MSG "DONE" fi From 900f75e3ebde8553a1c8f35f5397d88696a1a8f7 Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Mon, 5 Aug 2019 23:12:50 +0200 Subject: [PATCH 6/8] Add tests for validate_docstrings --- scripts/tests/test_validate_docstrings.py | 30 ++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/scripts/tests/test_validate_docstrings.py b/scripts/tests/test_validate_docstrings.py index f3364e6725a20..89aec60157598 100644 --- a/scripts/tests/test_validate_docstrings.py +++ b/scripts/tests/test_validate_docstrings.py @@ -200,7 +200,7 @@ def contains(self, pat, case=True, na=np.nan): def mode(self, axis, numeric_only): """ - Ensure sphinx directives don't affect checks for trailing periods. + Ensure reST directives don't affect checks for leading periods. Parameters ---------- @@ -447,6 +447,27 @@ def deprecation_in_wrong_order(self): def method_wo_docstrings(self): pass + def directives_without_two_colons(self, first, second): + """ + Ensure reST directives have trailing colons. + + Parameters + ---------- + first : str + Sentence ending in period, followed by single directive w/o colons. + + .. versionchanged 0.1.2 + + second : bool + Sentence ending in period, followed by multiple directives w/o + colons. + + .. versionadded 0.1.2 + .. deprecated 0.00.0 + + """ + pass + class BadSummaries: def wrong_line(self): @@ -840,6 +861,7 @@ def test_bad_class(self, capsys): "plot", "method", "private_classes", + "directives_without_two_colons", ], ) def test_bad_generic_functions(self, capsys, func): @@ -879,6 +901,12 @@ def test_bad_generic_functions(self, capsys, func): "deprecation_in_wrong_order", ("Deprecation warning should precede extended summary",), ), + ( + "BadGenericDocStrings", + "directives_without_two_colons", + ("reST directives ['versionchanged', 'versionadded', " + "'deprecated'] must be followed by two colons",), + ), ( "BadSeeAlso", "desc_no_period", From fd2fa5ac462a2be29a390809d34fc57adf8ddabd Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Tue, 6 Aug 2019 00:01:52 +0200 Subject: [PATCH 7/8] fix linting --- scripts/tests/test_validate_docstrings.py | 6 ++++-- scripts/validate_docstrings.py | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/scripts/tests/test_validate_docstrings.py b/scripts/tests/test_validate_docstrings.py index 89aec60157598..35aaf10458f44 100644 --- a/scripts/tests/test_validate_docstrings.py +++ b/scripts/tests/test_validate_docstrings.py @@ -904,8 +904,10 @@ def test_bad_generic_functions(self, capsys, func): ( "BadGenericDocStrings", "directives_without_two_colons", - ("reST directives ['versionchanged', 'versionadded', " - "'deprecated'] must be followed by two colons",), + ( + "reST directives ['versionchanged', 'versionadded', " + "'deprecated'] must be followed by two colons", + ), ), ( "BadSeeAlso", diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index 5bb78ef3a9b1d..d7b3b1a5b0f2a 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -59,9 +59,7 @@ PRIVATE_CLASSES = ["NDFrame", "IndexOpsMixin"] DIRECTIVES = ["versionadded", "versionchanged", "deprecated"] -DIRECTIVE_PATTERN = re.compile( - rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M -) +DIRECTIVE_PATTERN = re.compile(rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M) ALLOWED_SECTIONS = [ "Parameters", "Attributes", @@ -243,7 +241,6 @@ def get_api_items(api_doc_fd): class Docstring: - def __init__(self, name): self.name = name obj = self._load_obj(name) From e25a769a6ddcb30d5b8732c9927a7c7376aee5c2 Mon Sep 17 00:00:00 2001 From: Albert Villanova del Moral <8515462+albertvillanova@users.noreply.github.com> Date: Tue, 6 Aug 2019 00:13:24 +0200 Subject: [PATCH 8/8] Fix regex DIRECTIVE_PATTERN --- scripts/validate_docstrings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/validate_docstrings.py b/scripts/validate_docstrings.py index d7b3b1a5b0f2a..bf5d861281a36 100755 --- a/scripts/validate_docstrings.py +++ b/scripts/validate_docstrings.py @@ -59,7 +59,7 @@ PRIVATE_CLASSES = ["NDFrame", "IndexOpsMixin"] DIRECTIVES = ["versionadded", "versionchanged", "deprecated"] -DIRECTIVE_PATTERN = re.compile(rf"^\s*.. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M) +DIRECTIVE_PATTERN = re.compile(rf"^\s*\.\. ({'|'.join(DIRECTIVES)})(?!::)", re.I | re.M) ALLOWED_SECTIONS = [ "Parameters", "Attributes",