Skip to content

Commit 30a2e7f

Browse files
authored
CI: if no docstring, create error GL08 and don't validate - fix for numpydoc 1.9 (#61744)
* if no docstring, create error GL08 and don't validate * add file and file_line as None if no docstring
1 parent 35b0d1d commit 30a2e7f

File tree

1 file changed

+41
-31
lines changed

1 file changed

+41
-31
lines changed

scripts/validate_docstrings.py

Lines changed: 41 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,10 @@
6969
}
7070
ALL_ERRORS = set(NUMPYDOC_ERROR_MSGS).union(set(ERROR_MSGS))
7171
duplicated_errors = set(NUMPYDOC_ERROR_MSGS).intersection(set(ERROR_MSGS))
72-
assert not duplicated_errors, (f"Errors {duplicated_errors} exist in both pandas "
73-
"and numpydoc, should they be removed from pandas?")
72+
assert not duplicated_errors, (
73+
f"Errors {duplicated_errors} exist in both pandas "
74+
"and numpydoc, should they be removed from pandas?"
75+
)
7476

7577

7678
def pandas_error(code, **kwargs):
@@ -245,7 +247,15 @@ def pandas_validate(func_name: str):
245247
# Some objects are instances, e.g. IndexSlice, which numpydoc can't validate
246248
doc_obj = get_doc_object(func_obj, doc=func_obj.__doc__)
247249
doc = PandasDocstring(func_name, doc_obj)
248-
result = validate(doc_obj)
250+
if func_obj.__doc__ is not None:
251+
result = validate(doc_obj)
252+
else:
253+
result = {
254+
"docstring": "",
255+
"file": None,
256+
"file_line": None,
257+
"errors": [("GL08", "The object does not have a docstring")],
258+
}
249259
mentioned_errs = doc.mentioned_private_classes
250260
if mentioned_errs:
251261
result["errors"].append(
@@ -257,7 +267,7 @@ def pandas_validate(func_name: str):
257267
pandas_error(
258268
"SA05",
259269
reference_name=rel_name,
260-
right_reference=rel_name[len("pandas."):],
270+
right_reference=rel_name[len("pandas.") :],
261271
)
262272
for rel_name in doc.see_also
263273
if rel_name.startswith("pandas.")
@@ -365,12 +375,13 @@ def print_validate_all_results(
365375
for func_name, res in result.items():
366376
error_messages = dict(res["errors"])
367377
actual_failures = set(error_messages)
368-
expected_failures = (ignore_errors.get(func_name, set())
369-
| ignore_errors.get(None, set()))
378+
expected_failures = ignore_errors.get(func_name, set()) | ignore_errors.get(
379+
None, set()
380+
)
370381
for err_code in actual_failures - expected_failures:
371382
sys.stdout.write(
372383
f'{prefix}{res["file"]}:{res["file_line"]}:'
373-
f'{err_code}:{func_name}:{error_messages[err_code]}\n'
384+
f"{err_code}:{func_name}:{error_messages[err_code]}\n"
374385
)
375386
exit_status += 1
376387
for err_code in ignore_errors.get(func_name, set()) - actual_failures:
@@ -384,8 +395,9 @@ def print_validate_all_results(
384395
return exit_status
385396

386397

387-
def print_validate_one_results(func_name: str,
388-
ignore_errors: dict[str, set[str]]) -> int:
398+
def print_validate_one_results(
399+
func_name: str, ignore_errors: dict[str, set[str]]
400+
) -> int:
389401
def header(title, width=80, char="#") -> str:
390402
full_line = char * width
391403
side_len = (width - len(title) - 2) // 2
@@ -396,8 +408,11 @@ def header(title, width=80, char="#") -> str:
396408

397409
result = pandas_validate(func_name)
398410

399-
result["errors"] = [(code, message) for code, message in result["errors"]
400-
if code not in ignore_errors.get(None, set())]
411+
result["errors"] = [
412+
(code, message)
413+
for code, message in result["errors"]
414+
if code not in ignore_errors.get(None, set())
415+
]
401416

402417
sys.stderr.write(header(f"Docstring ({func_name})"))
403418
sys.stderr.write(f"{result['docstring']}\n")
@@ -431,14 +446,16 @@ def _format_ignore_errors(raw_ignore_errors):
431446
raise ValueError(
432447
f"Object `{obj_name}` is present in more than one "
433448
"--ignore_errors argument. Please use it once and specify "
434-
"the errors separated by commas.")
449+
"the errors separated by commas."
450+
)
435451
ignore_errors[obj_name] = set(error_codes.split(","))
436452

437453
unknown_errors = ignore_errors[obj_name] - ALL_ERRORS
438454
if unknown_errors:
439455
raise ValueError(
440456
f"Object `{obj_name}` is ignoring errors {unknown_errors} "
441-
f"which are not known. Known errors are: {ALL_ERRORS}")
457+
f"which are not known. Known errors are: {ALL_ERRORS}"
458+
)
442459

443460
# global errors "PR02,ES01"
444461
else:
@@ -448,27 +465,19 @@ def _format_ignore_errors(raw_ignore_errors):
448465
if unknown_errors:
449466
raise ValueError(
450467
f"Unknown errors {unknown_errors} specified using --ignore_errors "
451-
"Known errors are: {ALL_ERRORS}")
468+
"Known errors are: {ALL_ERRORS}"
469+
)
452470

453471
return ignore_errors
454472

455473

456-
def main(
457-
func_name,
458-
output_format,
459-
prefix,
460-
ignore_deprecated,
461-
ignore_errors
462-
):
474+
def main(func_name, output_format, prefix, ignore_deprecated, ignore_errors):
463475
"""
464476
Main entry point. Call the validation for one or for all docstrings.
465477
"""
466478
if func_name is None:
467479
return print_validate_all_results(
468-
output_format,
469-
prefix,
470-
ignore_deprecated,
471-
ignore_errors
480+
output_format, prefix, ignore_deprecated, ignore_errors
472481
)
473482
else:
474483
return print_validate_one_results(func_name, ignore_errors)
@@ -524,10 +533,11 @@ def main(
524533
args = argparser.parse_args(sys.argv[1:])
525534

526535
sys.exit(
527-
main(args.function,
528-
args.format,
529-
args.prefix,
530-
args.ignore_deprecated,
531-
_format_ignore_errors(args.ignore_errors),
532-
)
536+
main(
537+
args.function,
538+
args.format,
539+
args.prefix,
540+
args.ignore_deprecated,
541+
_format_ignore_errors(args.ignore_errors),
542+
)
533543
)

0 commit comments

Comments
 (0)