From fc81b259770808fba3d2107501d51fd091c8df94 Mon Sep 17 00:00:00 2001 From: Jarrod Millman Date: Fri, 9 Aug 2024 08:52:23 -0700 Subject: [PATCH 01/30] Bump version --- numpydoc/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpydoc/_version.py b/numpydoc/_version.py index 29654eec..fe918984 100644 --- a/numpydoc/_version.py +++ b/numpydoc/_version.py @@ -1 +1 @@ -__version__ = "1.8.0" +__version__ = "1.9.0rc0.dev0" From e478841c2c698465930c7e7a89a9faa29c4a0031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brigitta=20Sip=C5=91cz?= Date: Wed, 14 Aug 2024 08:12:30 -0700 Subject: [PATCH 02/30] CI: use hashes for actions' versions in publishing job (#579) --- .github/workflows/release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3320cf96..10fee7ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,10 +12,10 @@ jobs: name: sdist and wheels runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1 with: python-version: "3.12" - name: Build wheels @@ -24,7 +24,7 @@ jobs: pip install -U build twine wheel python -m build --sdist --wheel - run: twine check --strict dist/* - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 with: name: dist path: dist @@ -40,8 +40,8 @@ jobs: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: dist path: dist - - uses: pypa/gh-action-pypi-publish@release/v1 + - uses: pypa/gh-action-pypi-publish@ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0 # v1.9.0 From bc8ed844c59a8019d9d3362fd118f4b04ddc896d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 10:22:17 -0400 Subject: [PATCH 03/30] Bump the actions group with 2 updates (#581) Bumps the actions group with 2 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact) and [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish). Updates `actions/upload-artifact` from 4.3.6 to 4.4.0 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/834a144ee995460fba8ed112a2fc961b36a5ec5a...50769540e7f4bd5e21e526ee35c689e35e0d6874) Updates `pypa/gh-action-pypi-publish` from 1.9.0 to 1.10.0 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0...8a08d616893759ef8e1aa1f2785787c0b97e20d6) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10fee7ef..6cb6c6b2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: pip install -U build twine wheel python -m build --sdist --wheel - run: twine check --strict dist/* - - uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6 + - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 with: name: dist path: dist @@ -44,4 +44,4 @@ jobs: with: name: dist path: dist - - uses: pypa/gh-action-pypi-publish@ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0 # v1.9.0 + - uses: pypa/gh-action-pypi-publish@8a08d616893759ef8e1aa1f2785787c0b97e20d6 # v1.10.0 From fa0ccf45ebe1ce0db26fe4a1a405d9f62e3364fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:37:33 -0400 Subject: [PATCH 04/30] Bump pypa/gh-action-pypi-publish from 1.10.0 to 1.10.2 in the actions group (#582) Bump pypa/gh-action-pypi-publish in the actions group Bumps the actions group with 1 update: [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish). Updates `pypa/gh-action-pypi-publish` from 1.10.0 to 1.10.2 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/8a08d616893759ef8e1aa1f2785787c0b97e20d6...897895f1e160c830e369f9779632ebc134688e1b) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6cb6c6b2..b3cb5dae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -44,4 +44,4 @@ jobs: with: name: dist path: dist - - uses: pypa/gh-action-pypi-publish@8a08d616893759ef8e1aa1f2785787c0b97e20d6 # v1.10.0 + - uses: pypa/gh-action-pypi-publish@897895f1e160c830e369f9779632ebc134688e1b # v1.10.2 From bf210cc997f38c6f9bb012e12ea0aee28a5535c3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:06:39 -0400 Subject: [PATCH 05/30] [pre-commit.ci] pre-commit autoupdate (#583) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/pre-commit/pre-commit-hooks: 2c9f875913ee60ca25ce70243dc24d5b6415598c → cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b](https://github.com/pre-commit/pre-commit-hooks/compare/2c9f875913ee60ca25ce70243dc24d5b6415598c...cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b) - [github.com/pre-commit/mirrors-prettier: ffb6a759a979008c0e6dff86e39f4745a2d9eac4 → f12edd9c7be1c20cfa42420fd0e6df71e42b51ea](https://github.com/pre-commit/mirrors-prettier/compare/ffb6a759a979008c0e6dff86e39f4745a2d9eac4...f12edd9c7be1c20cfa42420fd0e6df71e42b51ea) - [github.com/astral-sh/ruff-pre-commit: 1dc9eb131c2ea4816c708e4d85820d2cc8542683 → 75b98813cfb7e663870a28c74366a1e99d7bfe79](https://github.com/astral-sh/ruff-pre-commit/compare/1dc9eb131c2ea4816c708e4d85820d2cc8542683...75b98813cfb7e663870a28c74366a1e99d7bfe79) * '[pre-commit.ci 🤖] Apply code format tools to PR' --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- numpydoc/tests/hooks/test_validate_hook.py | 2 +- numpydoc/tests/test_numpydoc.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 425c165f..0e4f84e6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,7 +3,7 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: 2c9f875913ee60ca25ce70243dc24d5b6415598c # frozen: v4.6.0 + rev: cef0300fd0fc4d2a87a85fa2093c6b283ea36f4b # frozen: v5.0.0 hooks: - id: check-added-large-files - id: check-ast @@ -18,14 +18,14 @@ repos: - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-prettier - rev: ffb6a759a979008c0e6dff86e39f4745a2d9eac4 # frozen: v3.1.0 + rev: f12edd9c7be1c20cfa42420fd0e6df71e42b51ea # frozen: v4.0.0-alpha.8 hooks: - id: prettier types_or: [yaml, toml, markdown, css, scss, javascript, json] args: [--prose-wrap=preserve] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "1dc9eb131c2ea4816c708e4d85820d2cc8542683" # frozen: v0.5.0 + rev: "75b98813cfb7e663870a28c74366a1e99d7bfe79" # frozen: v0.6.9 hooks: - id: ruff args: ["--fix", "--show-fixes", "--exit-non-zero-on-fix"] diff --git a/numpydoc/tests/hooks/test_validate_hook.py b/numpydoc/tests/hooks/test_validate_hook.py index 9a208cb0..ab71a871 100644 --- a/numpydoc/tests/hooks/test_validate_hook.py +++ b/numpydoc/tests/hooks/test_validate_hook.py @@ -8,7 +8,7 @@ from numpydoc.hooks.validate_docstrings import run_hook -@pytest.fixture() +@pytest.fixture def example_module(request): fullpath = ( Path(request.config.rootdir) diff --git a/numpydoc/tests/test_numpydoc.py b/numpydoc/tests/test_numpydoc.py index 30e6f602..f46e2565 100644 --- a/numpydoc/tests/test_numpydoc.py +++ b/numpydoc/tests/test_numpydoc.py @@ -142,7 +142,7 @@ def test_clean_text_signature(): assert _clean_text_signature("func($self, *args)") == "func(*args)" -@pytest.fixture() +@pytest.fixture def f(): def _function_without_seealso_and_examples(): """ From 1338660931330bfd881c2c5792ac7ac1ee3dab96 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Thu, 17 Oct 2024 07:21:24 -0700 Subject: [PATCH 06/30] MAINT: Add _exception_on_warning to MockApp (#586) MockApp in test suite is now breaking due to the absence of a private _exception_on_warning attribute. Fix by explicitly adding to the MockApp. --- numpydoc/tests/test_numpydoc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/numpydoc/tests/test_numpydoc.py b/numpydoc/tests/test_numpydoc.py index f46e2565..997cb0a5 100644 --- a/numpydoc/tests/test_numpydoc.py +++ b/numpydoc/tests/test_numpydoc.py @@ -49,6 +49,7 @@ def __init__(self): self.verbosity = 2 self._warncount = 0 self.warningiserror = False + self._exception_on_warning = False def test_mangle_docstrings_basic(): From 2af51f711c8610a86678f05543e19ca1b6f97853 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 17 Oct 2024 16:27:03 +0200 Subject: [PATCH 07/30] DOC: Do not use types for *args, **kwargs (#585) Docstrings are primarily intended for the caller, and there *args, **kwargs are not variables with a type but a signature pattern (this is also hinted at by using *args, **kwargs instead of args, kwargs as parameter names). It's rather confusing to try and type them, I'd even claim it's misleading and will tempt less experienced programmers to call `def func(*args)` with *args declared as tuple with a single tuple argument `func((1, 2, 3))`. This omission is also not an information loss for the few people, who look at the signature from the function body perspective (aka developers). That args and kwargs resolve to a tuple / dict in the function is a hard-coded fact. --- doc/format.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/format.rst b/doc/format.rst index 92cc2d36..6579191c 100644 --- a/doc/format.rst +++ b/doc/format.rst @@ -225,11 +225,11 @@ description, they can be combined:: Input arrays, description of `x1`, `x2`. When documenting variable length positional, or keyword arguments, leave the -leading star(s) in front of the name:: +leading star(s) in front of the name and do not specify a type:: - *args : tuple + *args Additional arguments should be passed as keyword arguments - **kwargs : dict, optional + **kwargs Extra arguments to `metric`: refer to each metric documentation for a list of all possible arguments. From a233ebf4919ccc717c6c56ba80ea1fb4437dbb78 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 09:41:23 -0500 Subject: [PATCH 08/30] Bump the actions group across 1 directory with 2 updates (#590) Bumps the actions group with 2 updates in the / directory: [actions/upload-artifact](https://github.com/actions/upload-artifact) and [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish). Updates `actions/upload-artifact` from 4.4.0 to 4.4.3 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/50769540e7f4bd5e21e526ee35c689e35e0d6874...b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882) Updates `pypa/gh-action-pypi-publish` from 1.10.2 to 1.12.2 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/897895f1e160c830e369f9779632ebc134688e1b...15c56dba361d8335944d31a2ecd17d700fc7bcbc) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3cb5dae..9ea6e46c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: pip install -U build twine wheel python -m build --sdist --wheel - run: twine check --strict dist/* - - uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0 + - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 with: name: dist path: dist @@ -44,4 +44,4 @@ jobs: with: name: dist path: dist - - uses: pypa/gh-action-pypi-publish@897895f1e160c830e369f9779632ebc134688e1b # v1.10.2 + - uses: pypa/gh-action-pypi-publish@15c56dba361d8335944d31a2ecd17d700fc7bcbc # v1.12.2 From 99786ec5bf8817abf50d80a8210e333fa879cb18 Mon Sep 17 00:00:00 2001 From: Lucas Colley Date: Mon, 16 Dec 2024 15:08:07 +0000 Subject: [PATCH 09/30] mention conda-forge in installation docs (#595) --- doc/install.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/install.rst b/doc/install.rst index 6282ffed..c72d777f 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -9,6 +9,7 @@ This extension requires Python 3.9+, sphinx 6+ and is available from: * `numpydoc on PyPI `_ * `numpydoc on GitHub `_ +* `numpydoc on conda-forge `_ `'numpydoc'` should be added to the ``extensions`` option in your Sphinx ``conf.py``. ``'sphinx.ext.autosummary'`` will automatically be loaded From d03b31c83b5c1980625c37aa0619ad36c208b99d Mon Sep 17 00:00:00 2001 From: Daniel McCloy Date: Tue, 17 Dec 2024 16:01:43 -0600 Subject: [PATCH 10/30] Don't pass maxsplit as positional arg (#596) --- numpydoc/docscrape_sphinx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpydoc/docscrape_sphinx.py b/numpydoc/docscrape_sphinx.py index 9b1ccf78..3b2f325a 100644 --- a/numpydoc/docscrape_sphinx.py +++ b/numpydoc/docscrape_sphinx.py @@ -160,7 +160,7 @@ def _process_param(self, param, desc, fake_autosummary): display_param = f":obj:`{param} <{link_prefix}{param}>`" if obj_doc: # Overwrite desc. Take summary logic of autosummary - desc = re.split(r"\n\s*\n", obj_doc.strip(), 1)[0] + desc = re.split(r"\n\s*\n", obj_doc.strip(), maxsplit=1)[0] # XXX: Should this have DOTALL? # It does not in autosummary m = re.search(r"^([A-Z].*?\.)(?:\s|$)", " ".join(desc.split())) From dec2b9e27c9cb82aa720d76fb432ec7aa27976d9 Mon Sep 17 00:00:00 2001 From: Lucas Colley Date: Mon, 23 Dec 2024 20:38:04 +0000 Subject: [PATCH 11/30] Ignore some errors at module level (#593) --- .gitignore | 1 + numpydoc/__main__.py | 4 +-- numpydoc/hooks/validate_docstrings.py | 4 +++ numpydoc/tests/hooks/test_validate_hook.py | 2 -- numpydoc/tests/test_main.py | 16 ++++------- numpydoc/validate.py | 33 +++++++++++++--------- 6 files changed, 32 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 26f7400b..60696edd 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ doc/_build numpydoc/tests/tinybuild/_build numpydoc/tests/tinybuild/generated MANIFEST +node_modules diff --git a/numpydoc/__main__.py b/numpydoc/__main__.py index b3b6d159..8cd0943e 100644 --- a/numpydoc/__main__.py +++ b/numpydoc/__main__.py @@ -1,6 +1,6 @@ """ -Implementing `python -m numpydoc` functionality. -""" +Implementing `python -m numpydoc` functionality +""" # '.' omitted at end of docstring for testing purposes! from .cli import main diff --git a/numpydoc/hooks/validate_docstrings.py b/numpydoc/hooks/validate_docstrings.py index 562a1f09..f5251522 100644 --- a/numpydoc/hooks/validate_docstrings.py +++ b/numpydoc/hooks/validate_docstrings.py @@ -60,6 +60,10 @@ def name(self) -> str: def is_function_or_method(self) -> bool: return isinstance(self.node, (ast.FunctionDef, ast.AsyncFunctionDef)) + @property + def is_mod(self) -> bool: + return self.is_module + @property def is_generator_function(self) -> bool: if not self.is_function_or_method: diff --git a/numpydoc/tests/hooks/test_validate_hook.py b/numpydoc/tests/hooks/test_validate_hook.py index ab71a871..18b03818 100644 --- a/numpydoc/tests/hooks/test_validate_hook.py +++ b/numpydoc/tests/hooks/test_validate_hook.py @@ -29,8 +29,6 @@ def test_validate_hook(example_module, config, capsys): +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ | file | item | check | description | +===========================================+=====================================+=========+====================================================+ - | numpydoc/tests/hooks/example_module.py:1 | example_module | EX01 | No examples section found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | ES01 | No extended summary found | +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index 12c06840..bd06be3f 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -117,7 +117,7 @@ def test_validate_perfect_docstring(): assert exit_status == 0 -@pytest.mark.parametrize("args", [[], ["--ignore", "ES01", "SA01", "EX01"]]) +@pytest.mark.parametrize("args", [[], ["--ignore", "SS03"]]) def test_lint(capsys, args): argv = ["lint", "numpydoc/__main__.py"] + args if args: @@ -126,15 +126,11 @@ def test_lint(capsys, args): else: expected = inspect.cleandoc( """ - +------------------------+----------+---------+----------------------------+ - | file | item | check | description | - +========================+==========+=========+============================+ - | numpydoc/__main__.py:1 | __main__ | ES01 | No extended summary found | - +------------------------+----------+---------+----------------------------+ - | numpydoc/__main__.py:1 | __main__ | SA01 | See Also section not found | - +------------------------+----------+---------+----------------------------+ - | numpydoc/__main__.py:1 | __main__ | EX01 | No examples section found | - +------------------------+----------+---------+----------------------------+ + +------------------------+----------+---------+------------------------------------+ + | file | item | check | description | + +========================+==========+=========+====================================+ + | numpydoc/__main__.py:1 | __main__ | SS03 | Summary does not end with a period | + +------------------------+----------+---------+------------------------------------+ """ ) expected_status = 1 diff --git a/numpydoc/validate.py b/numpydoc/validate.py index 138e9d48..495d7201 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -277,6 +277,10 @@ def type(self): def is_function_or_method(self): return inspect.isfunction(self.obj) + @property + def is_mod(self): + return inspect.ismodule(self.obj) + @property def is_generator_function(self): return inspect.isgeneratorfunction(_unwrap(self.obj)) @@ -690,7 +694,7 @@ def validate(obj_name, validator_cls=None, **validator_kwargs): if doc.num_summary_lines > 1: errs.append(error("SS06")) - if not doc.extended_summary: + if not doc.is_mod and not doc.extended_summary: errs.append(("ES01", "No extended summary found")) # PR01: Parameters not documented @@ -742,20 +746,21 @@ def validate(obj_name, validator_cls=None, **validator_kwargs): if not doc.yields and doc.is_generator_function: errs.append(error("YD01")) - if not doc.see_also: - errs.append(error("SA01")) - else: - for rel_name, rel_desc in doc.see_also.items(): - if rel_desc: - if not rel_desc.endswith("."): - errs.append(error("SA02", reference_name=rel_name)) - if rel_desc[0].isalpha() and not rel_desc[0].isupper(): - errs.append(error("SA03", reference_name=rel_name)) - else: - errs.append(error("SA04", reference_name=rel_name)) + if not doc.is_mod: + if not doc.see_also: + errs.append(error("SA01")) + else: + for rel_name, rel_desc in doc.see_also.items(): + if rel_desc: + if not rel_desc.endswith("."): + errs.append(error("SA02", reference_name=rel_name)) + if rel_desc[0].isalpha() and not rel_desc[0].isupper(): + errs.append(error("SA03", reference_name=rel_name)) + else: + errs.append(error("SA04", reference_name=rel_name)) - if not doc.examples: - errs.append(error("EX01")) + if not doc.examples: + errs.append(error("EX01")) errs = [err for err in errs if err[0] not in ignore_validation_comments] From e4a555428bae23eb5a1bfa5b93bac9b1b883dc67 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:18:20 -0500 Subject: [PATCH 12/30] [pre-commit.ci] pre-commit autoupdate (#598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: 75b98813cfb7e663870a28c74366a1e99d7bfe79 → 89c421dff2e1026ba12cdb9ebd731f4a83aa8021](https://github.com/astral-sh/ruff-pre-commit/compare/75b98813cfb7e663870a28c74366a1e99d7bfe79...89c421dff2e1026ba12cdb9ebd731f4a83aa8021) * '[pre-commit.ci 🤖] Apply code format tools to PR' --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- numpydoc/tests/test_docscrape.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e4f84e6..08185da6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: args: [--prose-wrap=preserve] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "75b98813cfb7e663870a28c74366a1e99d7bfe79" # frozen: v0.6.9 + rev: "89c421dff2e1026ba12cdb9ebd731f4a83aa8021" # frozen: v0.8.6 hooks: - id: ruff args: ["--fix", "--show-fixes", "--exit-non-zero-on-fix"] diff --git a/numpydoc/tests/test_docscrape.py b/numpydoc/tests/test_docscrape.py index 4cafc762..f10adc45 100644 --- a/numpydoc/tests/test_docscrape.py +++ b/numpydoc/tests/test_docscrape.py @@ -1596,8 +1596,8 @@ def __init__(self, a, b): self.numpydoc_validation_overrides = dict() xref_aliases_complete = deepcopy(DEFAULT_LINKS) - for key in xref_aliases: - xref_aliases_complete[key] = xref_aliases[key] + for key, val in xref_aliases.items(): + xref_aliases_complete[key] = val config = Config(xref_aliases, xref_aliases_complete) app = namedtuple("config", "config")(config) update_config(app) From b5cbfe35c231a9a698738923f323647e5650f4e4 Mon Sep 17 00:00:00 2001 From: Jarrod Millman Date: Thu, 9 Jan 2025 16:31:02 -0800 Subject: [PATCH 13/30] Add Python 3.13 support (#599) --- .github/workflows/test.yml | 4 ++-- pyproject.toml | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8eed0ce9..8db3074c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: os: [Ubuntu] - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] sphinx-version: ["sphinx==6.0", "sphinx==6.2", "sphinx==7.0", "sphinx>=7.3"] include: @@ -78,7 +78,7 @@ jobs: strategy: matrix: os: [ubuntu] - python-version: ["3.11", "3.12"] + python-version: ["3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 diff --git a/pyproject.toml b/pyproject.toml index 24dec3ee..04f18d86 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ classifiers = [ 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Topic :: Documentation', ] dependencies = [ From 06cd4a7e160d8f37be9f04db1cff883ca0faf304 Mon Sep 17 00:00:00 2001 From: Jarrod Millman Date: Thu, 9 Jan 2025 16:44:57 -0800 Subject: [PATCH 14/30] Update readthedocs config (#600) --- .readthedocs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index a124b7ca..252fca8e 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -6,9 +6,9 @@ version: 2 # Set the OS, Python version and other tools you might need build: - os: ubuntu-22.04 + os: ubuntu-24.04 tools: - python: "3.11" + python: "3.13" # You can also specify other tool versions: # nodejs: "19" # rust: "1.64" From 6d5eb428b8acea6ced4d86d086e36daf3f03ffbf Mon Sep 17 00:00:00 2001 From: Matt Gebert Date: Sat, 11 Jan 2025 02:25:24 +1100 Subject: [PATCH 15/30] MAINT: Changed class constructor __init__ GL08 reporting (#592) Co-authored-by: Stefan van der Walt Co-authored-by: Eric Larson --- doc/format.rst | 4 +- doc/validation.rst | 3 + numpydoc/tests/test_validate.py | 141 ++++++++++++++++++++++++++++++++ numpydoc/validate.py | 24 +++++- 4 files changed, 170 insertions(+), 2 deletions(-) diff --git a/doc/format.rst b/doc/format.rst index 6579191c..ecdd1d4f 100644 --- a/doc/format.rst +++ b/doc/format.rst @@ -557,7 +557,9 @@ Class docstring Use the same sections as outlined above (all except :ref:`Returns ` are applicable). The constructor (``__init__``) should also be documented here, the :ref:`Parameters ` section of the docstring details the -constructor's parameters. +constructor's parameters. While repetition is unnecessary, a docstring for +the class constructor (``__init__``) can, optionally, be added to provide +detailed initialization documentation. An **Attributes** section, located below the :ref:`Parameters ` section, may be used to describe non-method attributes of the class:: diff --git a/doc/validation.rst b/doc/validation.rst index aa9d5236..68844c2b 100644 --- a/doc/validation.rst +++ b/doc/validation.rst @@ -183,6 +183,9 @@ inline comments: def __init__(self): # numpydoc ignore=GL08 pass +Note that a properly formatted :ref:`class ` docstring +silences ``G08`` for an ``__init__`` constructor without a docstring. + This is supported by the :ref:`CLI `, :ref:`pre-commit hook `, and :ref:`Sphinx extension `. diff --git a/numpydoc/tests/test_validate.py b/numpydoc/tests/test_validate.py index 8b40794f..9f0f7942 100644 --- a/numpydoc/tests/test_validate.py +++ b/numpydoc/tests/test_validate.py @@ -1198,6 +1198,113 @@ def missing_whitespace_after_comma(self): """ +class ConstructorDocumentedInClassAndInit: + """ + Class to test constructor documented via class and constructor docstrings. + + A case where both the class docstring and the constructor docstring are + defined. + + Parameters + ---------- + param1 : int + Description of param1. + + See Also + -------- + otherclass : A class that does something else. + + Examples + -------- + This is an example of how to use ConstructorDocumentedInClassAndInit. + """ + + def __init__(self, param1: int) -> None: + """ + Constructor docstring with additional information. + + Extended information. + + Parameters + ---------- + param1 : int + Description of param1 with extra details. + + See Also + -------- + otherclass : A class that does something else. + + Examples + -------- + This is an example of how to use ConstructorDocumentedInClassAndInit. + """ + + +class ConstructorDocumentedInClass: + """ + Class to test constructor documented via class docstring. + + Useful to ensure that validation of `__init__` does not signal GL08, + when the class docstring properly documents the `__init__` constructor. + + Parameters + ---------- + param1 : int + Description of param1. + + See Also + -------- + otherclass : A class that does something else. + + Examples + -------- + This is an example of how to use ConstructorDocumentedInClass. + """ + + def __init__(self, param1: int) -> None: + pass + + +class ConstructorDocumentedInClassWithNoParameters: + """ + Class to test constructor documented via class docstring with no parameters. + + Useful to ensure that validation of `__init__` does not signal GL08, + when the class docstring properly documents the `__init__` constructor. + + See Also + -------- + otherclass : A class that does something else. + + Examples + -------- + This is an example of how to use ConstructorDocumentedInClassWithNoParameters. + """ + + def __init__(self) -> None: + pass + + +class IncompleteConstructorDocumentedInClass: + """ + Class to test an incomplete constructor docstring. + + This class does not properly document parameters. + Unnecessary extended summary. + + See Also + -------- + otherclass : A class that does something else. + + Examples + -------- + This is an example of how to use IncompleteConstructorDocumentedInClass. + """ + + def __init__(self, param1: int): + pass + + class TestValidator: def _import_path(self, klass=None, func=None): """ @@ -1536,6 +1643,40 @@ def test_bad_docstrings(self, capsys, klass, func, msgs): for msg in msgs: assert msg in " ".join(err[1] for err in result["errors"]) + @pytest.mark.parametrize( + "klass,exp_init_codes,exc_init_codes,exp_klass_codes", + [ + ("ConstructorDocumentedInClass", tuple(), ("GL08",), tuple()), + ("ConstructorDocumentedInClassAndInit", tuple(), ("GL08",), tuple()), + ( + "ConstructorDocumentedInClassWithNoParameters", + tuple(), + ("GL08",), + tuple(), + ), + ( + "IncompleteConstructorDocumentedInClass", + ("GL08",), + tuple(), + ("PR01"), # Parameter not documented in class constructor + ), + ], + ) + def test_constructor_docstrings( + self, klass, exp_init_codes, exc_init_codes, exp_klass_codes + ): + # First test the class docstring itself, checking expected_klass_codes match + result = validate_one(self._import_path(klass=klass)) + for err in result["errors"]: + assert err[0] in exp_klass_codes + + # Then test the constructor docstring + result = validate_one(self._import_path(klass=klass, func="__init__")) + for code in exp_init_codes: + assert code in " ".join(err[0] for err in result["errors"]) + for code in exc_init_codes: + assert code not in " ".join(err[0] for err in result["errors"]) + def decorator(x): """Test decorator.""" diff --git a/numpydoc/validate.py b/numpydoc/validate.py index 495d7201..858a06d2 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -637,7 +637,29 @@ def validate(obj_name, validator_cls=None, **validator_kwargs): errs = [] if not doc.raw_doc: - if "GL08" not in ignore_validation_comments: + report_GL08: bool = True + # Check if the object is a class and has a docstring in the constructor + # Also check if code_obj is defined, as undefined for the AstValidator in validate_docstrings.py. + if ( + doc.name.endswith(".__init__") + and doc.is_function_or_method + and hasattr(doc, "code_obj") + ): + cls_name = doc.code_obj.__qualname__.split(".")[0] + cls = Validator._load_obj(f"{doc.code_obj.__module__}.{cls_name}") + # cls = Validator._load_obj(f"{doc.name[:-9]}.{cls_name}") ## Alternative + cls_doc = Validator(get_doc_object(cls)) + + # Parameter_mismatches, PR01, PR02, PR03 are checked for the class docstring. + # If cls_doc has PR01, PR02, PR03 errors, i.e. invalid class docstring, + # then we also report missing constructor docstring, GL08. + report_GL08 = len(cls_doc.parameter_mismatches) > 0 + + # Check if GL08 is to be ignored: + if "GL08" in ignore_validation_comments: + report_GL08 = False + # Add GL08 error? + if report_GL08: errs.append(error("GL08")) return { "type": doc.type, From 7a6120bb972ee11a9bab7d533178b618ec8e947c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:50:56 -0500 Subject: [PATCH 16/30] Bump the actions group with 2 updates (#603) Bumps the actions group with 2 updates: [actions/upload-artifact](https://github.com/actions/upload-artifact) and [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish). Updates `actions/upload-artifact` from 4.4.3 to 4.6.0 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882...65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08) Updates `pypa/gh-action-pypi-publish` from 1.12.2 to 1.12.4 - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/15c56dba361d8335944d31a2ecd17d700fc7bcbc...76f52bc884231f62b9a034ebfe128415bbaabdfc) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ea6e46c..98567a5e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: pip install -U build twine wheel python -m build --sdist --wheel - run: twine check --strict dist/* - - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 + - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: dist path: dist @@ -44,4 +44,4 @@ jobs: with: name: dist path: dist - - uses: pypa/gh-action-pypi-publish@15c56dba361d8335944d31a2ecd17d700fc7bcbc # v1.12.2 + - uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 From 532cd7d71ceee4e00fd13fa5faf038f2b4d95905 Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Sat, 15 Feb 2025 12:58:51 -0500 Subject: [PATCH 17/30] Fix typo in validation.rst (#605) --- doc/validation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/validation.rst b/doc/validation.rst index 68844c2b..3d2babae 100644 --- a/doc/validation.rst +++ b/doc/validation.rst @@ -184,7 +184,7 @@ inline comments: pass Note that a properly formatted :ref:`class ` docstring -silences ``G08`` for an ``__init__`` constructor without a docstring. +silences ``GL08`` for an ``__init__`` constructor without a docstring. This is supported by the :ref:`CLI `, :ref:`pre-commit hook `, and From a36287a3be5ed71cf1cc4f67a3d7cc37fb12634d Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Tue, 11 Mar 2025 11:27:48 -0400 Subject: [PATCH 18/30] Rework hook output to remove the table (#611) * Switch from table to printed items * Remove tabulate dependency * Adjust format * Fix test after Sphinx builder change in newer version --- .pre-commit-hooks.yaml | 2 +- numpydoc/hooks/validate_docstrings.py | 27 ++-- numpydoc/tests/hooks/test_validate_hook.py | 176 +++++++++------------ numpydoc/tests/test_main.py | 10 +- numpydoc/tests/test_numpydoc.py | 1 + pyproject.toml | 1 - requirements/default.txt | 1 - 7 files changed, 86 insertions(+), 132 deletions(-) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 2244d460..69493db7 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -2,6 +2,6 @@ name: numpydoc-validation description: This hook validates that docstrings in committed files adhere to numpydoc standards. entry: numpydoc lint - require_serial: true + require_serial: false language: python types: [python] diff --git a/numpydoc/hooks/validate_docstrings.py b/numpydoc/hooks/validate_docstrings.py index f5251522..75ff2539 100644 --- a/numpydoc/hooks/validate_docstrings.py +++ b/numpydoc/hooks/validate_docstrings.py @@ -14,8 +14,6 @@ from pathlib import Path from typing import Any, Dict, List, Tuple, Union -from tabulate import tabulate - from .. import docscrape, validate from .utils import find_project_root @@ -193,7 +191,7 @@ def _get_numpydoc_issues(self, node: ast.AST) -> None: ) self.findings.extend( [ - [f'{self.filepath}:{report["file_line"]}', name, check, description] + [f"{self.filepath}:{report['file_line']}", name, check, description] for check, description in report["errors"] if not self._ignore_issue(node, check) ] @@ -371,19 +369,12 @@ def run_hook( config_options = parse_config(config or project_root) config_options["checks"] -= set(ignore or []) - findings = [] + findings = False for file in files: - findings.extend(process_file(file, config_options)) - - if findings: - print( - tabulate( - findings, - headers=["file", "item", "check", "description"], - tablefmt="grid", - maxcolwidths=50, - ), - file=sys.stderr, - ) - return 1 - return 0 + if file_issues := process_file(file, config_options): + findings = True + + for line, obj, check, description in file_issues: + print(f"\n{line}: {check} {description}", file=sys.stderr) + + return int(findings) diff --git a/numpydoc/tests/hooks/test_validate_hook.py b/numpydoc/tests/hooks/test_validate_hook.py index 18b03818..25851db5 100644 --- a/numpydoc/tests/hooks/test_validate_hook.py +++ b/numpydoc/tests/hooks/test_validate_hook.py @@ -26,53 +26,47 @@ def test_validate_hook(example_module, config, capsys): expected = inspect.cleandoc( """ - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | file | item | check | description | - +===========================================+=====================================+=========+====================================================+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | ES01 | No extended summary found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | SA01 | See Also section not found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | EX01 | No examples section found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:8 | example_module.MyClass | ES01 | No extended summary found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:8 | example_module.MyClass | SA01 | See Also section not found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:8 | example_module.MyClass | EX01 | No examples section found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:11 | example_module.MyClass.__init__ | GL08 | The object does not have a docstring | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | ES01 | No extended summary found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR01 | Parameters {'**kwargs'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR07 | Parameter "*args" has no description | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | SA01 | See Also section not found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | EX01 | No examples section found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:26 | example_module.MyClass.process | SS05 | Summary must start with infinitive verb, not third | - | | | | person (e.g. use "Generate" instead of | - | | | | "Generates") | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:26 | example_module.MyClass.process | ES01 | No extended summary found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:26 | example_module.MyClass.process | SA01 | See Also section not found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:26 | example_module.MyClass.process | EX01 | No examples section found | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:30 | example_module.NewClass | GL08 | The object does not have a docstring | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ + numpydoc/tests/hooks/example_module.py:4: ES01 No extended summary found + + numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not documented + + numpydoc/tests/hooks/example_module.py:4: SA01 See Also section not found + + numpydoc/tests/hooks/example_module.py:4: EX01 No examples section found + + numpydoc/tests/hooks/example_module.py:8: ES01 No extended summary found + + numpydoc/tests/hooks/example_module.py:8: SA01 See Also section not found + + numpydoc/tests/hooks/example_module.py:8: EX01 No examples section found + + numpydoc/tests/hooks/example_module.py:11: GL08 The object does not have a docstring + + numpydoc/tests/hooks/example_module.py:17: ES01 No extended summary found + + numpydoc/tests/hooks/example_module.py:17: PR01 Parameters {'**kwargs'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has no description + + numpydoc/tests/hooks/example_module.py:17: SA01 See Also section not found + + numpydoc/tests/hooks/example_module.py:17: EX01 No examples section found + + numpydoc/tests/hooks/example_module.py:26: SS05 Summary must start with infinitive verb, not third person (e.g. use "Generate" instead of "Generates") + + numpydoc/tests/hooks/example_module.py:26: ES01 No extended summary found + + numpydoc/tests/hooks/example_module.py:26: SA01 See Also section not found + + numpydoc/tests/hooks/example_module.py:26: EX01 No examples section found + + numpydoc/tests/hooks/example_module.py:30: GL08 The object does not have a docstring """ ) return_code = run_hook([example_module], config=config) assert return_code == 1 - assert capsys.readouterr().err.rstrip() == expected + assert capsys.readouterr().err.strip() == expected def test_validate_hook_with_ignore(example_module, capsys): @@ -83,30 +77,24 @@ def test_validate_hook_with_ignore(example_module, capsys): expected = inspect.cleandoc( """ - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | file | item | check | description | - +===========================================+=====================================+=========+====================================================+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:11 | example_module.MyClass.__init__ | GL08 | The object does not have a docstring | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR01 | Parameters {'**kwargs'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR07 | Parameter "*args" has no description | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:26 | example_module.MyClass.process | SS05 | Summary must start with infinitive verb, not third | - | | | | person (e.g. use "Generate" instead of | - | | | | "Generates") | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ - | numpydoc/tests/hooks/example_module.py:30 | example_module.NewClass | GL08 | The object does not have a docstring | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------------------+ + numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not documented + + numpydoc/tests/hooks/example_module.py:11: GL08 The object does not have a docstring + + numpydoc/tests/hooks/example_module.py:17: PR01 Parameters {'**kwargs'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has no description + + numpydoc/tests/hooks/example_module.py:26: SS05 Summary must start with infinitive verb, not third person (e.g. use "Generate" instead of "Generates") + + numpydoc/tests/hooks/example_module.py:30: GL08 The object does not have a docstring """ ) return_code = run_hook([example_module], ignore=["ES01", "SA01", "EX01"]) assert return_code == 1 - assert capsys.readouterr().err.rstrip() == expected + assert capsys.readouterr().err.strip() == expected def test_validate_hook_with_toml_config(example_module, tmp_path, capsys): @@ -138,23 +126,19 @@ def test_validate_hook_with_toml_config(example_module, tmp_path, capsys): expected = inspect.cleandoc( """ - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | file | item | check | description | - +===========================================+=====================================+=========+========================================+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR01 | Parameters {'**kwargs'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR07 | Parameter "*args" has no description | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:30 | example_module.NewClass | GL08 | The object does not have a docstring | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ + numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR01 Parameters {'**kwargs'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has no description + + numpydoc/tests/hooks/example_module.py:30: GL08 The object does not have a docstring """ ) return_code = run_hook([example_module], config=tmp_path) assert return_code == 1 - assert capsys.readouterr().err.rstrip() == expected + assert capsys.readouterr().err.strip() == expected def test_validate_hook_with_setup_cfg(example_module, tmp_path, capsys): @@ -177,23 +161,19 @@ def test_validate_hook_with_setup_cfg(example_module, tmp_path, capsys): expected = inspect.cleandoc( """ - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | file | item | check | description | - +===========================================+=====================================+=========+========================================+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR01 | Parameters {'**kwargs'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR07 | Parameter "*args" has no description | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:30 | example_module.NewClass | GL08 | The object does not have a docstring | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ + numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR01 Parameters {'**kwargs'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has no description + + numpydoc/tests/hooks/example_module.py:30: GL08 The object does not have a docstring """ ) return_code = run_hook([example_module], config=tmp_path) assert return_code == 1 - assert capsys.readouterr().err.rstrip() == expected + assert capsys.readouterr().err.strip() == expected def test_validate_hook_exclude_option_pyproject(example_module, tmp_path, capsys): @@ -228,19 +208,15 @@ def test_validate_hook_exclude_option_pyproject(example_module, tmp_path, capsys expected = inspect.cleandoc( """ - +-------------------------------------------+------------------------------+---------+--------------------------------------+ - | file | item | check | description | - +===========================================+==============================+=========+======================================+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | - +-------------------------------------------+------------------------------+---------+--------------------------------------+ - | numpydoc/tests/hooks/example_module.py:30 | example_module.NewClass | GL08 | The object does not have a docstring | - +-------------------------------------------+------------------------------+---------+--------------------------------------+ + numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not documented + + numpydoc/tests/hooks/example_module.py:30: GL08 The object does not have a docstring """ ) return_code = run_hook([example_module], config=tmp_path) assert return_code == 1 - assert capsys.readouterr().err.rstrip() == expected + assert capsys.readouterr().err.strip() == expected def test_validate_hook_exclude_option_setup_cfg(example_module, tmp_path, capsys): @@ -263,18 +239,14 @@ def test_validate_hook_exclude_option_setup_cfg(example_module, tmp_path, capsys expected = inspect.cleandoc( """ - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | file | item | check | description | - +===========================================+=====================================+=========+========================================+ - | numpydoc/tests/hooks/example_module.py:4 | example_module.some_function | PR01 | Parameters {'name'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR01 | Parameters {'**kwargs'} not documented | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ - | numpydoc/tests/hooks/example_module.py:17 | example_module.MyClass.do_something | PR07 | Parameter "*args" has no description | - +-------------------------------------------+-------------------------------------+---------+----------------------------------------+ + numpydoc/tests/hooks/example_module.py:4: PR01 Parameters {'name'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR01 Parameters {'**kwargs'} not documented + + numpydoc/tests/hooks/example_module.py:17: PR07 Parameter "*args" has no description """ ) return_code = run_hook([example_module], config=tmp_path) assert return_code == 1 - assert capsys.readouterr().err.rstrip() == expected + assert capsys.readouterr().err.strip() == expected diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index bd06be3f..e07e7df2 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -124,15 +124,7 @@ def test_lint(capsys, args): expected = "" expected_status = 0 else: - expected = inspect.cleandoc( - """ - +------------------------+----------+---------+------------------------------------+ - | file | item | check | description | - +========================+==========+=========+====================================+ - | numpydoc/__main__.py:1 | __main__ | SS03 | Summary does not end with a period | - +------------------------+----------+---------+------------------------------------+ - """ - ) + expected = "numpydoc/__main__.py:1: SS03 Summary does not end with a period" expected_status = 1 return_status = numpydoc.cli.main(argv) diff --git a/numpydoc/tests/test_numpydoc.py b/numpydoc/tests/test_numpydoc.py index 997cb0a5..bedef5fa 100644 --- a/numpydoc/tests/test_numpydoc.py +++ b/numpydoc/tests/test_numpydoc.py @@ -36,6 +36,7 @@ class MockConfig: class MockBuilder: config = MockConfig() + _translator = None class MockApp: diff --git a/pyproject.toml b/pyproject.toml index 04f18d86..53458910 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,6 @@ classifiers = [ ] dependencies = [ 'sphinx>=6', - 'tabulate>=0.8.10', "tomli>=1.1.0;python_version<'3.11'", ] diff --git a/requirements/default.txt b/requirements/default.txt index 5a1986a1..dfe792ef 100644 --- a/requirements/default.txt +++ b/requirements/default.txt @@ -1,5 +1,4 @@ # Generated via tools/generate_requirements.py and pre-commit hook. # Do not edit this file; modify pyproject.toml instead. sphinx>=6 -tabulate>=0.8.10 tomli>=1.1.0;python_version<'3.11' From fba6ee565b2bd886d3317f309c11b8790c7db44e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 06:54:56 -0700 Subject: [PATCH 19/30] Bump the actions group with 3 updates (#609) Bumps the actions group with 3 updates: [scientific-python/attach-next-milestone-action](https://github.com/scientific-python/attach-next-milestone-action), [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact). Updates `scientific-python/attach-next-milestone-action` from bc07be829f693829263e57d5e8489f4e57d3d420 to c9cfab10ad0c67fed91b01103db26b7f16634639 - [Release notes](https://github.com/scientific-python/attach-next-milestone-action/releases) - [Commits](https://github.com/scientific-python/attach-next-milestone-action/compare/bc07be829f693829263e57d5e8489f4e57d3d420...c9cfab10ad0c67fed91b01103db26b7f16634639) Updates `actions/upload-artifact` from 4.6.0 to 4.6.1 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08...4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1) Updates `actions/download-artifact` from 4.1.8 to 4.1.9 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/fa0a91b85d4f404e444e00e005971372dc801d16...cc203385981b70ca67e1cc392babf9cc229d5806) --- updated-dependencies: - dependency-name: scientific-python/attach-next-milestone-action dependency-type: direct:production dependency-group: actions - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/milestone-merged-prs.yml | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/milestone-merged-prs.yml b/.github/workflows/milestone-merged-prs.yml index 71ae037c..f455839d 100644 --- a/.github/workflows/milestone-merged-prs.yml +++ b/.github/workflows/milestone-merged-prs.yml @@ -12,7 +12,7 @@ jobs: name: attach to PR runs-on: ubuntu-latest steps: - - uses: scientific-python/attach-next-milestone-action@bc07be829f693829263e57d5e8489f4e57d3d420 + - uses: scientific-python/attach-next-milestone-action@c9cfab10ad0c67fed91b01103db26b7f16634639 with: token: ${{ secrets.MILESTONE_LABELER_TOKEN }} force: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98567a5e..131b9d43 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,7 +24,7 @@ jobs: pip install -U build twine wheel python -m build --sdist --wheel - run: twine check --strict dist/* - - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: dist path: dist @@ -40,7 +40,7 @@ jobs: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: - - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 with: name: dist path: dist From 08bf5f919048a6faca435c2dede025c96a975c71 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 12:59:25 -0400 Subject: [PATCH 20/30] [pre-commit.ci] pre-commit autoupdate (#614) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: 89c421dff2e1026ba12cdb9ebd731f4a83aa8021 → 971923581912ef60a6b70dbf0c3e9a39563c9d47](https://github.com/astral-sh/ruff-pre-commit/compare/89c421dff2e1026ba12cdb9ebd731f4a83aa8021...971923581912ef60a6b70dbf0c3e9a39563c9d47) * '[pre-commit.ci 🤖] Apply code format tools to PR' --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- numpydoc/cli.py | 9 +++++---- numpydoc/docscrape.py | 3 +-- numpydoc/validate.py | 3 +-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 08185da6..8e4d289d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: args: [--prose-wrap=preserve] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "89c421dff2e1026ba12cdb9ebd731f4a83aa8021" # frozen: v0.8.6 + rev: "971923581912ef60a6b70dbf0c3e9a39563c9d47" # frozen: v0.11.4 hooks: - id: ruff args: ["--fix", "--show-fixes", "--exit-non-zero-on-fix"] diff --git a/numpydoc/cli.py b/numpydoc/cli.py index ef8cff2c..53335fdf 100644 --- a/numpydoc/cli.py +++ b/numpydoc/cli.py @@ -104,10 +104,11 @@ def _parse_config(s): nargs="*", help=( f"""Check codes to ignore.{ - ' Currently ignoring the following from ' - f'{Path(project_root_from_cwd) / config_file}: {ignored_checks_text}' - 'Values provided here will be in addition to the above, unless an alternate config is provided.' - if ignored_checks else '' + " Currently ignoring the following from " + f"{Path(project_root_from_cwd) / config_file}: {ignored_checks_text}" + "Values provided here will be in addition to the above, unless an alternate config is provided." + if ignored_checks + else "" }""" ), ) diff --git a/numpydoc/docscrape.py b/numpydoc/docscrape.py index bfc2840e..54863d5f 100644 --- a/numpydoc/docscrape.py +++ b/numpydoc/docscrape.py @@ -232,8 +232,7 @@ def _parse_param_list(self, content, single_element_is_type=False): # NOTE: param line with single element should never have a # a " :" before the description line, so this should probably # warn. - if header.endswith(" :"): - header = header[:-2] + header = header.removesuffix(" :") if single_element_is_type: arg_name, arg_type = "", header else: diff --git a/numpydoc/validate.py b/numpydoc/validate.py index 858a06d2..db605949 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -80,8 +80,7 @@ "PR06": 'Parameter "{param_name}" type should use "{right_type}" instead ' 'of "{wrong_type}"', "PR07": 'Parameter "{param_name}" has no description', - "PR08": 'Parameter "{param_name}" description should start with a ' - "capital letter", + "PR08": 'Parameter "{param_name}" description should start with a capital letter', "PR09": 'Parameter "{param_name}" description should finish with "."', "PR10": 'Parameter "{param_name}" requires a space before the colon ' "separating the parameter name and type", From 5b437b5516f5222797e44dffd75274a51c54ae5d Mon Sep 17 00:00:00 2001 From: Maxine Hartnett <117409426+maxinelasp@users.noreply.github.com> Date: Tue, 15 Apr 2025 11:21:54 -0600 Subject: [PATCH 21/30] BUG: Correct functionality of numpydoc SS05 (#613) * BUG: Correct functionality of numpydoc SS05. Currently SS05 checks for infinitive verbs by checking if the last character is "s". However, if the first word is "process", which is valid, this incorrectly throws a numpydoc validation error. This commit allows the first word to end in two "s"es without flagging as an error. This will allow for words like "process" or "progress," while still checking for invalid words like "creates." * Update numpydoc/validate.py * FIX: Overrides --------- Co-authored-by: Eric Larson --- numpydoc/tests/hooks/example_module.py | 4 ++-- numpydoc/tests/hooks/test_validate_hook.py | 12 ++++-------- numpydoc/validate.py | 8 +++++++- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/numpydoc/tests/hooks/example_module.py b/numpydoc/tests/hooks/example_module.py index 87e9b52d..9f75bdf0 100644 --- a/numpydoc/tests/hooks/example_module.py +++ b/numpydoc/tests/hooks/example_module.py @@ -23,8 +23,8 @@ def do_something(self, *args, **kwargs): *args """ - def process(self): - """Process stuff.""" + def create(self): + """Creates stuff.""" class NewClass: diff --git a/numpydoc/tests/hooks/test_validate_hook.py b/numpydoc/tests/hooks/test_validate_hook.py index 25851db5..47f315c2 100644 --- a/numpydoc/tests/hooks/test_validate_hook.py +++ b/numpydoc/tests/hooks/test_validate_hook.py @@ -116,9 +116,7 @@ def test_validate_hook_with_toml_config(example_module, tmp_path, capsys): ] exclude = '\\.__init__$' override_SS05 = [ - '^Process', - '^Assess', - '^Access', + '^Creates', ] """ ) @@ -154,7 +152,7 @@ def test_validate_hook_with_setup_cfg(example_module, tmp_path, capsys): [tool:numpydoc_validation] checks = all,EX01,SA01,ES01 exclude = \\.__init__$ - override_SS05 = ^Process,^Assess,^Access + override_SS05 = ^Creates """ ) ) @@ -198,9 +196,7 @@ def test_validate_hook_exclude_option_pyproject(example_module, tmp_path, capsys '\.__init__$', ] override_SS05 = [ - '^Process', - '^Assess', - '^Access', + '^Creates', ] """ ) @@ -232,7 +228,7 @@ def test_validate_hook_exclude_option_setup_cfg(example_module, tmp_path, capsys [tool:numpydoc_validation] checks = all,EX01,SA01,ES01 exclude = \\.NewClass$,\\.__init__$ - override_SS05 = ^Process,^Assess,^Access + override_SS05 = ^Creates """ ) ) diff --git a/numpydoc/validate.py b/numpydoc/validate.py index db605949..d0debfa2 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -710,7 +710,13 @@ def validate(obj_name, validator_cls=None, **validator_kwargs): errs.append(error("SS03")) if doc.summary != doc.summary.lstrip(): errs.append(error("SS04")) - elif doc.is_function_or_method and doc.summary.split(" ")[0][-1] == "s": + # Heuristic to check for infinitive verbs - shouldn't end in "s" + elif ( + doc.is_function_or_method + and len(doc.summary.split(" ")[0]) > 1 + and doc.summary.split(" ")[0][-1] == "s" + and doc.summary.split(" ")[0][-2] != "s" + ): errs.append(error("SS05")) if doc.num_summary_lines > 1: errs.append(error("SS06")) From 9862b6a5afde6003d67e26a6d7d775e2132ef55f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 May 2025 12:57:48 -0400 Subject: [PATCH 22/30] Bump actions/download-artifact from 4.2.1 to 4.3.0 in the actions group (#620) Bumps the actions group with 1 update: [actions/download-artifact](https://github.com/actions/download-artifact). Updates `actions/download-artifact` from 4.2.1 to 4.3.0 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/95815c38cf2ff2164869cbab79da8d1f422bc89e...d3f86a106a0bac45b974a628896c90dbdf5c8093) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: 4.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 131b9d43..dc0b7a30 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,7 +40,7 @@ jobs: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: - - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4.2.1 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: dist path: dist From 8dbddc68a4a7a67b9209461010f47434c18e7bf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 08:44:12 -0600 Subject: [PATCH 23/30] Bump scientific-python/circleci-artifacts-redirector-action from 1.0.0 to 1.1.0 in the actions group (#627) Bump scientific-python/circleci-artifacts-redirector-action Bumps the actions group with 1 update: [scientific-python/circleci-artifacts-redirector-action](https://github.com/scientific-python/circleci-artifacts-redirector-action). Updates `scientific-python/circleci-artifacts-redirector-action` from 1.0.0 to 1.1.0 - [Release notes](https://github.com/scientific-python/circleci-artifacts-redirector-action/releases) - [Commits](https://github.com/scientific-python/circleci-artifacts-redirector-action/compare/4e13a10d89177f4bfc8007a7064bdbeda848d8d1...7eafdb60666f57706a5525a2f5eb76224dc8779b) --- updated-dependencies: - dependency-name: scientific-python/circleci-artifacts-redirector-action dependency-version: 1.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6d52fc24..0353ba98 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,7 @@ jobs: name: Run CircleCI artifacts redirector steps: - name: GitHub Action step - uses: scientific-python/circleci-artifacts-redirector-action@4e13a10d89177f4bfc8007a7064bdbeda848d8d1 # v1.0.0 + uses: scientific-python/circleci-artifacts-redirector-action@7eafdb60666f57706a5525a2f5eb76224dc8779b # v1.1.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} api-token: ${{ secrets.CIRCLECI_ARTIFACT_REDIRECTOR_TOKEN }} From 84ebcc022b2a44bae4c56f90e4ed4e1c1b69723e Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 2 Jun 2025 11:47:46 -0400 Subject: [PATCH 24/30] Switch to dependency groups (#626) * Switch to dependency groups * Override install step to use dependency group --- .circleci/config.yml | 2 +- .github/workflows/test.yml | 4 ++-- .pre-commit-config.yaml | 8 ------- .readthedocs.yaml | 15 ++++--------- MANIFEST.in | 1 - pyproject.toml | 6 ++++-- requirements/default.txt | 4 ---- requirements/developer.txt | 4 ---- requirements/doc.txt | 7 ------ requirements/test.txt | 5 ----- tools/generate_requirements.py | 39 ---------------------------------- 11 files changed, 11 insertions(+), 84 deletions(-) delete mode 100644 requirements/default.txt delete mode 100644 requirements/developer.txt delete mode 100644 requirements/doc.txt delete mode 100644 requirements/test.txt delete mode 100755 tools/generate_requirements.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 66a60c8d..98cae9bc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,7 +20,7 @@ jobs: python3 -m venv venv source venv/bin/activate python -m pip install --upgrade pip wheel setuptools - python -m pip install --upgrade -r requirements/doc.txt + python -m pip install --upgrade --group doc python -m pip list - save_cache: key: pip-cache diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8db3074c..b6c46a46 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,7 +43,7 @@ jobs: - name: Install run: | - python -m pip install .[test,doc] + python -m pip install . --group test --group doc pip list - name: Run test suite @@ -95,7 +95,7 @@ jobs: - name: Install run: | - python -m pip install .[test,doc] + python -m pip install . --group test --group doc pip list - name: Run test suite diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8e4d289d..1fa15182 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,14 +31,6 @@ repos: args: ["--fix", "--show-fixes", "--exit-non-zero-on-fix"] - id: ruff-format - - repo: local - hooks: - - id: generate_requirements.py - name: generate_requirements.py - language: system - entry: python tools/generate_requirements.py - files: "pyproject.toml|requirements/.*\\.txt|tools/generate_requirements.py" - ci: autofix_prs: false autofix_commit_msg: | diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 252fca8e..ebc00e82 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -13,22 +13,15 @@ build: # nodejs: "19" # rust: "1.64" # golang: "1.19" + jobs: + install: + - python -m pip install --upgrade pip wheel setuptools + - python -m pip install . --group doc # Build documentation in the "doc/" directory with Sphinx sphinx: configuration: doc/conf.py - # Optionally build your docs in additional formats such as PDF and ePub # formats: # - pdf # - epub - -# Optional but recommended, declare the Python requirements required -# to build your documentation -# See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -python: - install: - - method: pip - path: . - extra_requirements: - - doc diff --git a/MANIFEST.in b/MANIFEST.in index d1508eee..0a6df3ac 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,7 +2,6 @@ include MANIFEST.in include *.txt include *.rst recursive-include doc * -recursive-include requirements * recursive-include numpydoc * # Exclude what we don't want to include diff --git a/pyproject.toml b/pyproject.toml index 53458910..b6acaa4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,10 +43,12 @@ file = 'LICENSE.txt' Homepage = 'https://numpydoc.readthedocs.io' Source = 'https://github.com/numpy/numpydoc/' -[project.optional-dependencies] -developer = [ +[dependency-groups] +dev = [ 'pre-commit>=3.3', "tomli; python_version < '3.11'", + { include-group = "doc" }, + { include-group = "test" } ] doc = [ 'numpy>=1.22', diff --git a/requirements/default.txt b/requirements/default.txt deleted file mode 100644 index dfe792ef..00000000 --- a/requirements/default.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Generated via tools/generate_requirements.py and pre-commit hook. -# Do not edit this file; modify pyproject.toml instead. -sphinx>=6 -tomli>=1.1.0;python_version<'3.11' diff --git a/requirements/developer.txt b/requirements/developer.txt deleted file mode 100644 index dbeefe57..00000000 --- a/requirements/developer.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Generated via tools/generate_requirements.py and pre-commit hook. -# Do not edit this file; modify pyproject.toml instead. -pre-commit>=3.3 -tomli; python_version < '3.11' diff --git a/requirements/doc.txt b/requirements/doc.txt deleted file mode 100644 index 950966b6..00000000 --- a/requirements/doc.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Generated via tools/generate_requirements.py and pre-commit hook. -# Do not edit this file; modify pyproject.toml instead. -numpy>=1.22 -matplotlib>=3.5 -pydata-sphinx-theme>=0.13.3 -sphinx>=7 -intersphinx_registry diff --git a/requirements/test.txt b/requirements/test.txt deleted file mode 100644 index 2a9e670f..00000000 --- a/requirements/test.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Generated via tools/generate_requirements.py and pre-commit hook. -# Do not edit this file; modify pyproject.toml instead. -pytest -pytest-cov -matplotlib diff --git a/tools/generate_requirements.py b/tools/generate_requirements.py deleted file mode 100755 index 388d2ccc..00000000 --- a/tools/generate_requirements.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -"""Generate requirements/*.txt files from pyproject.toml.""" - -import sys -from pathlib import Path - -try: # standard module since Python 3.11 - import tomllib as toml -except ImportError: - try: # available for older Python via pip - import tomli as toml - except ImportError: - sys.exit("Please install `tomli` first: `pip install tomli`") - -script_pth = Path(__file__) -repo_dir = script_pth.parent.parent -script_relpth = script_pth.relative_to(repo_dir) -header = [ - f"# Generated via {script_relpth.as_posix()} and pre-commit hook.", - "# Do not edit this file; modify pyproject.toml instead.", -] - - -def generate_requirement_file(name: str, req_list: list[str]) -> None: - req_fname = repo_dir / "requirements" / f"{name}.txt" - req_fname.write_text("\n".join(header + req_list) + "\n") - - -def main() -> None: - pyproject = toml.loads((repo_dir / "pyproject.toml").read_text()) - - generate_requirement_file("default", pyproject["project"]["dependencies"]) - - for key, opt_list in pyproject["project"]["optional-dependencies"].items(): - generate_requirement_file(key, opt_list) - - -if __name__ == "__main__": - main() From 139a3441554ca74270a93cfcc7486035cf2557cc Mon Sep 17 00:00:00 2001 From: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> Date: Mon, 2 Jun 2025 11:49:36 -0400 Subject: [PATCH 25/30] Switch to storing AST nodes on the stack for more accurate method signature check and easy access to parent nodes (#623) Switch to storing AST nodes on the stack for more accurate method signature check --- numpydoc/hooks/validate_docstrings.py | 51 ++++++++++++++++++++------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/numpydoc/hooks/validate_docstrings.py b/numpydoc/hooks/validate_docstrings.py index 75ff2539..aa318e47 100644 --- a/numpydoc/hooks/validate_docstrings.py +++ b/numpydoc/hooks/validate_docstrings.py @@ -33,7 +33,12 @@ class AstValidator(validate.Validator): """ def __init__( - self, *, ast_node: ast.AST, filename: os.PathLike, obj_name: str + self, + *, + ast_node: ast.AST, + filename: os.PathLike, + obj_name: str, + ancestry: list[ast.AST], ) -> None: self.node: ast.AST = ast_node self.raw_doc: str = ast.get_docstring(self.node, clean=False) or "" @@ -46,6 +51,8 @@ def __init__( self.is_class: bool = isinstance(ast_node, ast.ClassDef) self.is_module: bool = isinstance(ast_node, ast.Module) + self.ancestry: list[ast.AST] = ancestry + @staticmethod def _load_obj(name): raise NotImplementedError("AstValidator does not support this method.") @@ -91,7 +98,7 @@ def source_file_def_line(self) -> int: @property def signature_parameters(self) -> Tuple[str]: - def extract_signature(node): + def extract_signature(node, parent): args_node = node.args params = [] for arg_type in ["posonlyargs", "args", "vararg", "kwonlyargs", "kwarg"]: @@ -104,17 +111,21 @@ def extract_signature(node): else: params.extend([arg.arg for arg in entries]) params = tuple(params) - if params and params[0] in {"self", "cls"}: + if ( + params + and params[0] in {"self", "cls"} + and isinstance(parent, ast.ClassDef) + ): return params[1:] return params params = tuple() if self.is_function_or_method: - params = extract_signature(self.node) + params = extract_signature(self.node, self.ancestry[-1]) elif self.is_class: for child in self.node.body: if isinstance(child, ast.FunctionDef) and child.name == "__init__": - params = extract_signature(child) + params = extract_signature(child, self.node) return params @property @@ -144,9 +155,23 @@ def __init__( self.config: dict = config self.filepath: str = filepath self.module_name: str = Path(self.filepath).stem - self.stack: list[str] = [] + self.stack: list[ast.AST] = [] self.findings: list = [] + @property + def node_name(self) -> str: + """ + Get the full name of the current node in the stack. + + Returns + ------- + str + The full name of the current node in the stack. + """ + return ".".join( + [getattr(node, "name", self.module_name) for node in self.stack] + ) + def _ignore_issue(self, node: ast.AST, check: str) -> bool: """ Check whether the issue should be ignored. @@ -185,9 +210,13 @@ def _get_numpydoc_issues(self, node: ast.AST) -> None: node : ast.AST The node under inspection. """ - name = ".".join(self.stack) + name = self.node_name report = validate.validate( - name, AstValidator, ast_node=node, filename=self.filepath + name, + AstValidator, + ast_node=node, + filename=self.filepath, + ancestry=self.stack[:-1], ) self.findings.extend( [ @@ -209,13 +238,11 @@ def visit(self, node: ast.AST) -> None: if isinstance( node, (ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef) ): - self.stack.append( - self.module_name if isinstance(node, ast.Module) else node.name - ) + self.stack.append(node) if not ( self.config["exclude"] - and re.search(self.config["exclude"], ".".join(self.stack)) + and re.search(self.config["exclude"], self.node_name) ): self._get_numpydoc_issues(node) From 259f8ac8291485c1b11dda83e6ad29c4231d724c Mon Sep 17 00:00:00 2001 From: Gilles Peiffer Date: Mon, 2 Jun 2025 22:33:13 +0200 Subject: [PATCH 26/30] Fix broken link in `format.rst` (#628) --- doc/format.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/format.rst b/doc/format.rst index ecdd1d4f..3b3693a4 100644 --- a/doc/format.rst +++ b/doc/format.rst @@ -769,9 +769,9 @@ leads to the following style recommendations: enclosed within ````double backticks````. A more extensive example of reST markup can be found in `this example -document `_; +document `_; the `quick reference -`_ is +`_ is useful while editing. Line spacing and indentation are significant and should be carefully From 865b865b3d1dfb8cd2139fa76cefe3643e1bf52a Mon Sep 17 00:00:00 2001 From: Yuki Kobayashi Date: Wed, 4 Jun 2025 14:01:32 +0900 Subject: [PATCH 27/30] Fix pip setup command in github workflow (#629) --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b6c46a46..b463ee42 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,7 +38,7 @@ jobs: run: | python -m pip install --upgrade pip wheel setuptools python -m pip install codecov - python -m pip install ${{ matrix.sphinx-version }} + python -m pip install "${{ matrix.sphinx-version }}" python -m pip list - name: Install From 80441357dcf5bd8197ad9fa8a9447c07c1f2da29 Mon Sep 17 00:00:00 2001 From: Yuki Kobayashi Date: Sat, 7 Jun 2025 13:41:51 +0900 Subject: [PATCH 28/30] Specity the types of `numpydoc_xref_ignore` option (#631) Added `types` parameter to accept the value `"all"` for the `numpydoc_xref_ignore` option. Fixes gh-630 --- numpydoc/numpydoc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpydoc/numpydoc.py b/numpydoc/numpydoc.py index a04443b3..9a920e35 100644 --- a/numpydoc/numpydoc.py +++ b/numpydoc/numpydoc.py @@ -296,7 +296,7 @@ def setup(app, get_doc_object_=get_doc_object): app.add_config_value("numpydoc_attributes_as_param_list", True, True) app.add_config_value("numpydoc_xref_param_type", False, True) app.add_config_value("numpydoc_xref_aliases", dict(), True) - app.add_config_value("numpydoc_xref_ignore", set(), True) + app.add_config_value("numpydoc_xref_ignore", set(), True, types=[set, str]) app.add_config_value("numpydoc_validation_checks", set(), True) app.add_config_value("numpydoc_validation_exclude", set(), False) app.add_config_value("numpydoc_validation_overrides", dict(), False) From 610a25e4d33114df619b88c3e8083ec11b9729d0 Mon Sep 17 00:00:00 2001 From: Jarrod Millman Date: Tue, 24 Jun 2025 05:15:02 -0700 Subject: [PATCH 29/30] Designate 1.9.0rc0 release --- numpydoc/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpydoc/_version.py b/numpydoc/_version.py index fe918984..b3de187d 100644 --- a/numpydoc/_version.py +++ b/numpydoc/_version.py @@ -1 +1 @@ -__version__ = "1.9.0rc0.dev0" +__version__ = "1.9.0rc0" From 3db2f68e5a6af0de867f9ec1ea94c6052d1d824f Mon Sep 17 00:00:00 2001 From: Jarrod Millman Date: Tue, 24 Jun 2025 05:18:49 -0700 Subject: [PATCH 30/30] Designate 1.9.0 release --- doc/release/notes.rst | 79 +++++++++++++++++++++++++++++++++++++++++++ numpydoc/_version.py | 2 +- 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/doc/release/notes.rst b/doc/release/notes.rst index ad1ccda1..74406b6a 100644 --- a/doc/release/notes.rst +++ b/doc/release/notes.rst @@ -1,3 +1,82 @@ +1.9.0 +===== + +We're happy to announce the release of numpydoc 1.9.0! + +Enhancements +------------ + +- ignore some errors at module level (`#593 `_). +- Rework hook output to remove the table (`#611 `_). +- Switch to storing AST nodes on the stack for more accurate method signature check and easy access to parent nodes (`#623 `_). + +Bug Fixes +--------- + +- MAINT: Changed class constructor __init__ GL08 reporting (`#592 `_). +- BUG: Correct functionality of numpydoc SS05 (`#613 `_). +- Specity the types of ``numpydoc_xref_ignore`` option (`#631 `_). + +Documentation +------------- + +- DOC: Do not use types for *args, **kwargs (`#585 `_). +- mention conda-forge in installation docs (`#595 `_). +- Fix typo in validation.rst (`#605 `_). +- Fix broken link in ``format.rst`` (`#628 `_). + +Maintenance +----------- + +- CI: use hashes for actions' versions in publishing job (`#579 `_). +- Bump the actions group with 2 updates (`#581 `_). +- Bump pypa/gh-action-pypi-publish from 1.10.0 to 1.10.2 in the actions group (`#582 `_). +- [pre-commit.ci] pre-commit autoupdate (`#583 `_). +- MAINT: Add _exception_on_warning to MockApp (`#586 `_). +- Bump the actions group across 1 directory with 2 updates (`#590 `_). +- don't pass maxsplit as positional arg (`#596 `_). +- [pre-commit.ci] pre-commit autoupdate (`#598 `_). +- Add Python 3.13 support (`#599 `_). +- Update readthedocs config (`#600 `_). +- Bump the actions group with 2 updates (`#603 `_). +- Bump the actions group with 3 updates (`#609 `_). +- [pre-commit.ci] pre-commit autoupdate (`#614 `_). +- Bump actions/download-artifact from 4.2.1 to 4.3.0 in the actions group (`#620 `_). +- Bump scientific-python/circleci-artifacts-redirector-action from 1.0.0 to 1.1.0 in the actions group (`#627 `_). +- Switch to dependency groups (`#626 `_). +- Fix pip setup command in github workflow (`#629 `_). + +Contributors +------------ + +13 authors added to this release (alphabetically): + +- Brigitta Sipőcz (`@bsipocz `_) +- Daniel McCloy (`@drammock `_) +- Eric Larson (`@larsoner `_) +- Gilles Peiffer (`@Peiffap `_) +- Jarrod Millman (`@jarrodmillman `_) +- Lucas Colley (`@lucascolley `_) +- Matt Gebert (`@mattgebert `_) +- Maxine Hartnett (`@maxinelasp `_) +- Ross Barnowski (`@rossbar `_) +- Stefan van der Walt (`@stefanv `_) +- Stefanie Molin (`@stefmolin `_) +- Tim Hoffmann (`@timhoffm `_) +- Yuki Kobayashi (`@koyuki7w `_) + +7 reviewers added to this release (alphabetically): + +- Charles Harris (`@charris `_) +- Eric Larson (`@larsoner `_) +- Jarrod Millman (`@jarrodmillman `_) +- Lucas Colley (`@lucascolley `_) +- Matt Gebert (`@mattgebert `_) +- Ross Barnowski (`@rossbar `_) +- Stefan van der Walt (`@stefanv `_) + +_These lists are automatically generated, and may not be complete or may contain duplicates._ + 1.8.0 ===== diff --git a/numpydoc/_version.py b/numpydoc/_version.py index b3de187d..0a0a43a5 100644 --- a/numpydoc/_version.py +++ b/numpydoc/_version.py @@ -1 +1 @@ -__version__ = "1.9.0rc0" +__version__ = "1.9.0" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy