Skip to content

Commit a58ab90

Browse files
authored
Pre-commit hook for running numpydoc validation (#454)
* Add numpydoc.hooks directory. * Add numpydoc.hooks to packages. * Add tabulate dependency for use in validate hook. * Add option to pass a Validator class to validate() function. * Add AST-based validation logic to review files. * Add entry point for validation hook. * Add pre-commit hook configuration. * Add SS05 match pattern for allowed verbs; add some type annotations. * Add config option to override GL08 by name. * Add option specify a path to a config file. * Add information on the hook to the docs. * Grab arg name off ast arg nodes for *args/**kwargs; don't alter filepath. * Update spacing in example. * Reduce maxcolwidths in report of findings by hook. * Show file in a separate column of the findings; item is from module onward. * Update example in docs for new column. * Update example in docs for new column. * Switch to a stack for visiting. * Add line to file column; show module lineno as 1. * Expand user on config file path. * Use Path operations. * Add support for using inline comments to ignore specific checks. * Add support for comments at the end of a multiline declaration. * Add a note on inline option to docs. * Simplify check for the declaration start. * Add support for reading hook config from pyproject.toml * Add some initial tests for the validate hook. * Tweak docstring. * Add tests for hook using config files. * Add finding of project root. * Update link in docstring. * Tweak code blocks in docs. * Shorten table to avoid scroll in docs.
1 parent 4c740e4 commit a58ab90

12 files changed

+844
-6
lines changed

.pre-commit-hooks.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
- id: numpydoc-validation
2+
name: numpydoc-validation
3+
description: This hook validates that docstrings in committed files adhere to numpydoc standards.
4+
entry: validate-docstrings
5+
require_serial: true
6+
language: python
7+
types: [python]

doc/validation.rst

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,83 @@
22
Validation
33
==========
44

5+
Docstring Validation using Pre-Commit Hook
6+
------------------------------------------
7+
8+
To enable validation of docstrings as you commit files, add the
9+
following to your ``.pre-commit-config.yaml`` file:
10+
11+
.. code-block:: yaml
12+
13+
- repo: https://github.com/numpy/numpydoc
14+
rev: <version>
15+
hooks:
16+
- id: numpydoc-validation
17+
18+
After installing ``numpydoc``, run the following to see available
19+
command line options for this hook:
20+
21+
.. code-block:: bash
22+
23+
$ python -m numpydoc.hooks.validate_docstrings --help
24+
25+
Using a config file provides additional customization. Both
26+
``pyproject.toml`` and ``setup.cfg`` are supported; however, if the
27+
project contains both you must use the ``pyproject.toml`` file.
28+
The example below configures the pre-commit hook to ignore three checks
29+
and specifies exceptions to the checks ``SS05`` (allow docstrings to
30+
start with "Process ", "Assess ", or "Access ") and ``GL08`` (allow
31+
the class/method/function with name "__init__" to not have a docstring).
32+
33+
``pyproject.toml``::
34+
35+
[tool.numpydoc_validation]
36+
ignore = [
37+
"EX01",
38+
"SA01",
39+
"ES01",
40+
]
41+
override_SS05 = '^((Process|Assess|Access) )'
42+
override_GL08 = '^(__init__)$'
43+
44+
``setup.cfg``::
45+
46+
[tool:numpydoc_validation]
47+
ignore = EX01,SA01,ES01
48+
override_SS05 = ^((Process|Assess|Access) )
49+
override_GL08 = ^(__init__)$
50+
51+
For more fine-tuned control, you can also include inline comments to tell the
52+
validation hook to ignore certain checks:
53+
54+
.. code-block:: python
55+
56+
class SomeClass: # numpydoc ignore=EX01,SA01,ES01
57+
"""This is the docstring for SomeClass."""
58+
59+
def __init__(self): # numpydoc ignore=GL08
60+
pass
61+
62+
If any issues are found when commiting, a report is printed out and the
63+
commit is halted:
64+
65+
.. code-block:: output
66+
67+
numpydoc-validation......................................................Failed
68+
- hook id: numpydoc-validation
69+
- exit code: 1
70+
71+
+----------------------+----------------------+---------+--------------------------------------+
72+
| file | item | check | description |
73+
+======================+======================+=========+======================================+
74+
| src/pkg/utils.py:1 | utils | GL08 | The object does not have a docstring |
75+
| src/pkg/utils.py:90 | utils.normalize | PR04 | Parameter "field" has no type |
76+
| src/pkg/module.py:12 | module.MyClass | GL08 | The object does not have a docstring |
77+
| src/pkg/module.py:33 | module.MyClass.parse | RT03 | Return value has no description |
78+
+----------------------+----------------------+---------+--------------------------------------+
79+
80+
See below for a full listing of checks.
81+
582
Docstring Validation using Python
683
---------------------------------
784

numpydoc/hooks/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Pre-commit hooks using numpydoc."""

numpydoc/hooks/utils.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""Utility functions for pre-commit hooks."""
2+
3+
import itertools
4+
import os
5+
from pathlib import Path
6+
from typing import Sequence
7+
8+
9+
def find_project_root(srcs: Sequence[str]):
10+
"""
11+
Return a directory containing .git, .hg, pyproject.toml, or setup.cfg.
12+
13+
That directory can be one of the directories passed in ``srcs`` or their
14+
common parent. If no directory in the tree contains a marker that would
15+
specify it's the project root, the root of the file system is returned.
16+
17+
Parameters
18+
----------
19+
srcs : Sequence[str]
20+
The filepaths to run the hook on.
21+
22+
Returns
23+
-------
24+
str
25+
The project root directory.
26+
27+
See Also
28+
--------
29+
black.find_project_root :
30+
This function was adapted from
31+
`Black <https://github.com/psf/black/blob/main/src/black/files.py>`_.
32+
"""
33+
if not srcs:
34+
return Path(".").resolve(), "current directory"
35+
36+
common_path = Path(
37+
os.path.commonpath([Path(src).expanduser().resolve() for src in srcs])
38+
)
39+
40+
for dir in itertools.chain([common_path], common_path.parents):
41+
if (dir / "pyproject.toml").is_file():
42+
return dir, "pyproject.toml"
43+
if (dir / "setup.cfg").is_file():
44+
return dir, "setup.cfg"
45+
if (dir / ".git").exists() or (dir / ".hg").is_dir():
46+
return dir, "version control"
47+
48+
return dir, "file system root"

0 commit comments

Comments
 (0)