Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-commit hook for running numpydoc validation #454

Merged
merged 35 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6e3b468
Add numpydoc.hooks directory.
stefmolin Feb 19, 2023
6d5b54e
Add numpydoc.hooks to packages.
stefmolin Feb 19, 2023
3d4ba71
Add tabulate dependency for use in validate hook.
stefmolin Feb 19, 2023
2b0a962
Add option to pass a Validator class to validate() function.
stefmolin Feb 19, 2023
ed9ba3c
Add AST-based validation logic to review files.
stefmolin Feb 19, 2023
fb53cee
Add entry point for validation hook.
stefmolin Feb 19, 2023
c18c990
Add pre-commit hook configuration.
stefmolin Feb 19, 2023
f7df258
Add SS05 match pattern for allowed verbs; add some type annotations.
stefmolin Feb 19, 2023
ee49b0d
Add config option to override GL08 by name.
stefmolin Feb 19, 2023
2409e43
Add option specify a path to a config file.
stefmolin Feb 19, 2023
a4fdc71
Add information on the hook to the docs.
stefmolin Feb 19, 2023
749feee
Grab arg name off ast arg nodes for *args/**kwargs; don't alter filep…
stefmolin Feb 19, 2023
8f4457b
Update spacing in example.
stefmolin Feb 19, 2023
34061f3
Reduce maxcolwidths in report of findings by hook.
stefmolin Feb 19, 2023
056bcd8
Show file in a separate column of the findings; item is from module o…
stefmolin Feb 20, 2023
56f6320
Update example in docs for new column.
stefmolin Feb 20, 2023
26ac09e
Update example in docs for new column.
stefmolin Feb 20, 2023
5d9584d
Switch to a stack for visiting.
stefmolin Feb 20, 2023
afa2509
Add line to file column; show module lineno as 1.
stefmolin Feb 21, 2023
cead4ae
Expand user on config file path.
stefmolin Feb 24, 2023
195d35b
Use Path operations.
stefmolin Feb 25, 2023
9d73d6a
Add support for using inline comments to ignore specific checks.
stefmolin Feb 26, 2023
8e59535
Add support for comments at the end of a multiline declaration.
stefmolin Feb 26, 2023
629c65c
Add a note on inline option to docs.
stefmolin Feb 26, 2023
405affb
Simplify check for the declaration start.
stefmolin Feb 26, 2023
e2e42ba
Add support for reading hook config from pyproject.toml
stefmolin Mar 4, 2023
4e0707b
Add some initial tests for the validate hook.
stefmolin Mar 4, 2023
97fc2dd
Tweak docstring.
stefmolin Mar 4, 2023
223ed2d
Add tests for hook using config files.
stefmolin Mar 4, 2023
f4663d3
Add finding of project root.
stefmolin Mar 4, 2023
583b6b1
Update link in docstring.
stefmolin Mar 4, 2023
281c04d
Tweak code blocks in docs.
stefmolin Mar 4, 2023
09281fd
Merge branch 'main' into ast-validate-hook
stefmolin Mar 4, 2023
6a1a606
Shorten table to avoid scroll in docs.
stefmolin Mar 4, 2023
262dbef
Merge branch 'main' into ast-validate-hook
stefmolin Jun 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- id: numpydoc-validation
name: numpydoc-validation
description: This hook validates that docstrings in committed files adhere to numpydoc standards.
entry: validate-docstrings
require_serial: true
language: python
types: [python]
77 changes: 77 additions & 0 deletions doc/validation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,83 @@
Validation
==========

Docstring Validation using Pre-Commit Hook
------------------------------------------

To enable validation of docstrings as you commit files, add the
following to your ``.pre-commit-config.yaml`` file:

.. code-block:: yaml

- repo: https://github.com/numpy/numpydoc
rev: <version>
hooks:
- id: numpydoc-validation

After installing ``numpydoc``, run the following to see available
command line options for this hook:

.. code-block:: bash

$ python -m numpydoc.hooks.validate_docstrings --help
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for now, but longer term I'm wondering if we shouldn't consolidate everything under python -m numpydoc, which currently has questionable semantics. E.g., to a new user this must be clear as mud:

$ python -m numpydoc --help
usage: __main__.py [-h] [-c CONFIG] [--validate] import_path

Implementing `python -m numpydoc` functionality.

positional arguments:
  import_path           e.g. numpy.ndarray

options:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        key=val where val will be parsed by literal_eval, e.g. -c use_plots=True. Multiple -c can be used.
  --validate            validate the object and report errors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I'm happy to work on this, but I think we first need to discuss whether we are comfortable changing this interface (for example, if we had subparsers to split up the current functionality and the new hook). Probably best to save this discussion for an issue dedicated to the topic though 😊


Using a config file provides additional customization. Both
``pyproject.toml`` and ``setup.cfg`` are supported; however, if the
project contains both you must use the ``pyproject.toml`` file.
The example below configures the pre-commit hook to ignore three checks
and specifies exceptions to the checks ``SS05`` (allow docstrings to
start with "Process ", "Assess ", or "Access ") and ``GL08`` (allow
the class/method/function with name "__init__" to not have a docstring).

``pyproject.toml``::

[tool.numpydoc_validation]
ignore = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loving this!

"EX01",
"SA01",
"ES01",
]
override_SS05 = '^((Process|Assess|Access) )'
override_GL08 = '^(__init__)$'

``setup.cfg``::

[tool:numpydoc_validation]
ignore = EX01,SA01,ES01
override_SS05 = ^((Process|Assess|Access) )
override_GL08 = ^(__init__)$

For more fine-tuned control, you can also include inline comments to tell the
validation hook to ignore certain checks:

.. code-block:: python

class SomeClass: # numpydoc ignore=EX01,SA01,ES01
"""This is the docstring for SomeClass."""

def __init__(self): # numpydoc ignore=GL08
pass

If any issues are found when commiting, a report is printed out and the
commit is halted:

.. code-block:: output

numpydoc-validation......................................................Failed
- hook id: numpydoc-validation
- exit code: 1

+----------------------+----------------------+---------+--------------------------------------+
| file | item | check | description |
+======================+======================+=========+======================================+
| src/pkg/utils.py:1 | utils | GL08 | The object does not have a docstring |
| src/pkg/utils.py:90 | utils.normalize | PR04 | Parameter "field" has no type |
| src/pkg/module.py:12 | module.MyClass | GL08 | The object does not have a docstring |
| src/pkg/module.py:33 | module.MyClass.parse | RT03 | Return value has no description |
+----------------------+----------------------+---------+--------------------------------------+

See below for a full listing of checks.

Docstring Validation using Python
---------------------------------

Expand Down
1 change: 1 addition & 0 deletions numpydoc/hooks/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Pre-commit hooks using numpydoc."""
48 changes: 48 additions & 0 deletions numpydoc/hooks/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Utility functions for pre-commit hooks."""

import itertools
import os
from pathlib import Path
from typing import Sequence


def find_project_root(srcs: Sequence[str]):
"""
Return a directory containing .git, .hg, pyproject.toml, or setup.cfg.

That directory can be one of the directories passed in ``srcs`` or their
common parent. If no directory in the tree contains a marker that would
specify it's the project root, the root of the file system is returned.

Parameters
----------
srcs : Sequence[str]
The filepaths to run the hook on.

Returns
-------
str
The project root directory.

See Also
--------
black.find_project_root :
This function was adapted from
`Black <https://github.com/psf/black/blob/main/src/black/files.py>`_.
"""
if not srcs:
return Path(".").resolve(), "current directory"

common_path = Path(
os.path.commonpath([Path(src).expanduser().resolve() for src in srcs])
)

for dir in itertools.chain([common_path], common_path.parents):
if (dir / "pyproject.toml").is_file():
return dir, "pyproject.toml"
if (dir / "setup.cfg").is_file():
return dir, "setup.cfg"
if (dir / ".git").exists() or (dir / ".hg").is_dir():
return dir, "version control"

return dir, "file system root"
Loading