From a1cd426decb47fc29f318fdcbda91801d33b771f Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Sat, 31 Jul 2021 16:20:10 -0700 Subject: [PATCH 1/3] DOC: Ensure all pandas.errors are documents in general_utility_functions.rst --- .pre-commit-config.yaml | 5 +++ .../reference/general_utility_functions.rst | 3 ++ pandas/errors/__init__.py | 2 +- scripts/pandas_errors_documented.py | 32 +++++++++++++++++++ 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 scripts/pandas_errors_documented.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3a07aae11dc1b..5d0d788c8aa7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -136,3 +136,8 @@ repos: entry: python scripts/no_bool_in_generic.py language: python files: ^pandas/core/generic\.py$ + - id: pandas-errors-documented + name: Ensure pandas errors are documented in doc/source/reference/general_utility_functions.rst + entry: python scripts/pandas_errors_documented.py + language: python + files: ^doc/source/reference/general_utility_functions.rst$ diff --git a/doc/source/reference/general_utility_functions.rst b/doc/source/reference/general_utility_functions.rst index 37fe980dbf68c..ee17ef3831164 100644 --- a/doc/source/reference/general_utility_functions.rst +++ b/doc/source/reference/general_utility_functions.rst @@ -35,14 +35,17 @@ Exceptions and warnings .. autosummary:: :toctree: api/ + errors.AbstractMethodError errors.AccessorRegistrationWarning errors.DtypeWarning errors.DuplicateLabelError errors.EmptyDataError errors.InvalidIndexError + errors.IntCastingNaNError errors.MergeError errors.NullFrequencyError errors.NumbaUtilError + errors.OptionError errors.OutOfBoundsDatetime errors.OutOfBoundsTimedelta errors.ParserError diff --git a/pandas/errors/__init__.py b/pandas/errors/__init__.py index 92516a1609f10..56eda37c8122e 100644 --- a/pandas/errors/__init__.py +++ b/pandas/errors/__init__.py @@ -14,7 +14,7 @@ class IntCastingNaNError(ValueError): """ - raised when attempting an astype operation on an array with NaN to an integer + Raised when attempting an astype operation on an array with NaN to an integer dtype. """ diff --git a/scripts/pandas_errors_documented.py b/scripts/pandas_errors_documented.py new file mode 100644 index 0000000000000..cada4d4a9eb7c --- /dev/null +++ b/scripts/pandas_errors_documented.py @@ -0,0 +1,32 @@ +""" +Check that doc/source/reference/general_utility_functions.rst documents all exceptions and +warnings in pandas/errors/__init__.py. + +This is meant to be run as a pre-commit hook - to run it manually, you can do: + + pre-commit run pandas-errors-documented --all-files +""" +import inspect +import sys + +from pandas import errors + + +API_PATH = "doc/source/reference/general_utility_functions.rst" + + +def main(): + with open(API_PATH, "r") as f: + api_docs = f.read() + missing = [] + for obj in errors.__dict__.values(): + if inspect.isclass(obj) and issubclass(obj, (Exception, Warning)) and obj.__name__ not in api_docs: + missing.append(obj.__name__) + if missing: + sys.stdout.write(f"The follow exceptions and/or warnings are not documented in {API_PATH}: {missing}") + sys.exit(1) + sys.exit(0) + + +if __name__ == "__main__": + main() From faaaa3b1446458ae3a5a0b1f9b390c2f51b096c7 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Fri, 13 Aug 2021 17:04:33 -0700 Subject: [PATCH 2/3] Use ast to check for the errors --- .pre-commit-config.yaml | 2 +- scripts/pandas_errors_documented.py | 53 ++++++++++++++++++++--------- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5c4afa3f011b..eb0abe1829fc6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -168,4 +168,4 @@ repos: name: Ensure pandas errors are documented in doc/source/reference/general_utility_functions.rst entry: python scripts/pandas_errors_documented.py language: python - files: ^doc/source/reference/general_utility_functions.rst$ + files: ^pandas/errors/__init__.py$ diff --git a/scripts/pandas_errors_documented.py b/scripts/pandas_errors_documented.py index cada4d4a9eb7c..a527cdc328b8a 100644 --- a/scripts/pandas_errors_documented.py +++ b/scripts/pandas_errors_documented.py @@ -1,31 +1,50 @@ """ -Check that doc/source/reference/general_utility_functions.rst documents all exceptions and -warnings in pandas/errors/__init__.py. +Check that doc/source/reference/general_utility_functions.rst documents +all exceptions and warnings in pandas/errors/__init__.py. This is meant to be run as a pre-commit hook - to run it manually, you can do: pre-commit run pandas-errors-documented --all-files """ -import inspect -import sys - -from pandas import errors +from __future__ import annotations +import argparse +import ast +import sys +from typing import Sequence API_PATH = "doc/source/reference/general_utility_functions.rst" -def main(): - with open(API_PATH, "r") as f: - api_docs = f.read() - missing = [] - for obj in errors.__dict__.values(): - if inspect.isclass(obj) and issubclass(obj, (Exception, Warning)) and obj.__name__ not in api_docs: - missing.append(obj.__name__) - if missing: - sys.stdout.write(f"The follow exceptions and/or warnings are not documented in {API_PATH}: {missing}") - sys.exit(1) - sys.exit(0) +def get_defined_errors(content: str) -> set[str]: + errors = set() + for node in ast.walk(ast.parse(content)): + if isinstance(node, ast.ClassDef): + errors.add(node.name) + elif isinstance(node, ast.ImportFrom): + for alias in node.names: + errors.add(alias.name) + return errors + + +def main(argv: Sequence[str] | None = None) -> None: + parser = argparse.ArgumentParser() + parser.add_argument("path") + args = parser.parse_args(argv) + with open(args.path, encoding="utf-8") as f: + file_errors = get_defined_errors(f.read()) + with open(API_PATH) as f: + doc_errors = { + line.split(".")[1].strip() for line in f.readlines() if "errors" in line + } + missing = file_errors.difference(doc_errors) + if missing: + sys.stdout.write( + f"The follow exceptions and/or warnings are not documented " + f"in {API_PATH}: {missing}" + ) + sys.exit(1) + sys.exit(0) if __name__ == "__main__": From 78c01f42b720e3753901ce7d513133c043d31de0 Mon Sep 17 00:00:00 2001 From: Matthew Roeschke Date: Tue, 17 Aug 2021 21:12:04 -0700 Subject: [PATCH 3/3] Use pathlib to ensure Windows support --- scripts/pandas_errors_documented.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/pandas_errors_documented.py b/scripts/pandas_errors_documented.py index a527cdc328b8a..4024cd24c558e 100644 --- a/scripts/pandas_errors_documented.py +++ b/scripts/pandas_errors_documented.py @@ -10,10 +10,11 @@ import argparse import ast +import pathlib import sys from typing import Sequence -API_PATH = "doc/source/reference/general_utility_functions.rst" +API_PATH = pathlib.Path("doc/source/reference/general_utility_functions.rst").resolve() def get_defined_errors(content: str) -> set[str]: