From 6fb5f064453996865e0061e83ba3b04e7f9df230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=87=BA=F0=9F=87=A6=20Sviatoslav=20Sydorenko=20=28?= =?UTF-8?q?=D0=A1=D0=B2=D1=8F=D1=82=D0=BE=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1?= =?UTF-8?q?=D0=B8=D0=B4=D0=BE=D1=80=D0=B5=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 25 Nov 2024 17:11:01 +0100 Subject: [PATCH 01/56] =?UTF-8?q?=F0=9F=90=9B=20Replace=20docutils=20priva?= =?UTF-8?q?te=20API=20use=20w/=20public=20(#507)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #454 Ref https://sourceforge.net/p/docutils/bugs/496. --- src/sphinx_autodoc_typehints/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index e67180f8..ce41602b 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -13,7 +13,7 @@ from typing import TYPE_CHECKING, Any, AnyStr, ForwardRef, NewType, TypeVar, get_type_hints from docutils import nodes -from docutils.frontend import OptionParser +from docutils.frontend import get_default_settings from sphinx.ext.autodoc.mock import mock from sphinx.parsers import RSTParser from sphinx.util import logging, rst @@ -849,7 +849,7 @@ def get_insert_index(app: Sphinx, lines: list[str]) -> InsertIndexInfo | None: # 3. Insert after the parameters. # To find the parameters, parse as a docutils tree. - settings = OptionParser(components=(RSTParser,)).get_default_values() + settings = get_default_settings(RSTParser) settings.env = app.env doc = parse("\n".join(lines), settings) From bf8bb8d4cc4c4ddab95aaa6e184cfac07bd39693 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:25:42 -0800 Subject: [PATCH 02/56] Bump astral-sh/setup-uv from 3 to 4 (#506) Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 3 to 4. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v3...v4) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 0316ecb7..ecda4f81 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -33,7 +33,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v4 with: enable-cache: true cache-dependency-glob: "pyproject.toml" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 8612092b..31c88224 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@v4 with: enable-cache: true cache-dependency-glob: "pyproject.toml" From 17ccd64ad50312ac28b034b64ac339df749cc3f9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:42:04 -0800 Subject: [PATCH 03/56] [pre-commit.ci] pre-commit autoupdate (#508) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/python-jsonschema/check-jsonschema: 0.29.4 → 0.30.0](https://github.com/python-jsonschema/check-jsonschema/compare/0.29.4...0.30.0) - [github.com/astral-sh/ruff-pre-commit: v0.7.4 → v0.8.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.4...v0.8.2) - [github.com/rbubley/mirrors-prettier: v3.3.3 → v3.4.2](https://github.com/rbubley/mirrors-prettier/compare/v3.3.3...v3.4.2) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- src/sphinx_autodoc_typehints/__init__.py | 6 +++--- tests/test_integration_autodoc_type_aliases.py | 2 +- tests/test_sphinx_autodoc_typehints.py | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b88f80dd..282e453b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.29.4 + rev: 0.30.0 hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,13 +24,13 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.7.4" + rev: "v0.8.2" hooks: - id: ruff-format - id: ruff args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier - rev: "v3.3.3" # Use the sha / tag you want to point at + rev: "v3.4.2" # Use the sha / tag you want to point at hooks: - id: prettier additional_dependencies: diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index ce41602b..fd5db7a4 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -417,14 +417,14 @@ def _is_dataclass(name: str, what: str, qualname: str) -> bool: def _future_annotations_imported(obj: Any) -> bool: - _annotations = getattr(inspect.getmodule(obj), "annotations", None) - if _annotations is None: + annotations_ = getattr(inspect.getmodule(obj), "annotations", None) + if annotations_ is None: return False # Make sure that annotations is imported from __future__ - defined in cpython/Lib/__future__.py # annotations become strings at runtime future_annotations = 0x100000 if sys.version_info[0:2] == (3, 7) else 0x1000000 - return bool(_annotations.compiler_flag == future_annotations) + return bool(annotations_.compiler_flag == future_annotations) def get_all_type_hints( diff --git a/tests/test_integration_autodoc_type_aliases.py b/tests/test_integration_autodoc_type_aliases.py index b3063fea..9d5a9511 100644 --- a/tests/test_integration_autodoc_type_aliases.py +++ b/tests/test_integration_autodoc_type_aliases.py @@ -151,7 +151,7 @@ def test_integration( if regexp: msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" assert re.search(regexp, value), msg - elif not re.search("WARNING: Inline strong start-string without end-string.", value): + elif not re.search(r"WARNING: Inline strong start-string without end-string.", value): assert not value result = (Path(app.srcdir) / "_build/text/index.txt").read_text() diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index 4e8041ff..acc5aca2 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -491,7 +491,7 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str # Test for the correct role (class vs data) using the official Sphinx inventory if "typing" in expected_result: - m = re.match("^:py:(?Pclass|data|func):`~(?P[^`]+)`", result) + m = re.match(r"^:py:(?Pclass|data|func):`~(?P[^`]+)`", result) assert m, "No match" name = m.group("name") expected_role = next((o.role for o in inv.objects if o.name == name), None) @@ -905,7 +905,7 @@ def test_resolve_typing_guard_imports(app: SphinxTestApp, status: StringIO, warn out = status.getvalue() assert "build succeeded" in out err = warning.getvalue() - r = re.compile("WARNING: Failed guarded type import") + r = re.compile(r"WARNING: Failed guarded type import") assert len(r.findall(err)) == 1 pat = r'WARNING: Failed guarded type import with ImportError\("cannot import name \'missing\' from \'functools\'' assert re.search(pat, err) From 85f00aee3ac25bb779f6c5a9f5f919d5a4c4342c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 20:31:47 -0800 Subject: [PATCH 04/56] Bump pypa/gh-action-pypi-publish from 1.12.2 to 1.12.3 (#509) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.2 to 1.12.3. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.2...v1.12.3) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 31c88224..80705953 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,6 +43,6 @@ jobs: name: ${{ env.dists-artifact-name }} path: dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.2 + uses: pypa/gh-action-pypi-publish@v1.12.3 with: attestations: true From 80e67888c95c11a8ac81cabbbd84dc35a5d0d312 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Jan 2025 16:41:51 -0800 Subject: [PATCH 05/56] Bump astral-sh/setup-uv from 4 to 5 (#512) Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 4 to 5. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v4...v5) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index ecda4f81..08004343 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -33,7 +33,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v4 + uses: astral-sh/setup-uv@v5 with: enable-cache: true cache-dependency-glob: "pyproject.toml" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 80705953..df296276 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v4 + uses: astral-sh/setup-uv@v5 with: enable-cache: true cache-dependency-glob: "pyproject.toml" From 3af8fb6f6a681d00e88c422bdc5e18ed0158c0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Thu, 2 Jan 2025 16:45:06 -0800 Subject: [PATCH 06/56] Drop support for nptyping (#514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernát Gábor --- .pre-commit-config.yaml | 6 +- CHANGELOG.md | 320 ------------------ pyproject.toml | 21 +- src/sphinx_autodoc_typehints/__init__.py | 9 +- tests/conftest.py | 16 +- .../demo_typing_guard.py | 2 +- tests/test_integration.py | 4 - tests/test_sphinx_autodoc_typehints.py | 139 ++------ tox.ini | 16 +- whitelist.txt | 90 ----- 10 files changed, 61 insertions(+), 562 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 282e453b..04461d8b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: rev: v2.3.0 hooks: - id: codespell - additional_dependencies: ["tomli>=2.0.1"] + additional_dependencies: ["tomli>=2.2.1"] - repo: https://github.com/tox-dev/tox-ini-fmt rev: "1.4.1" hooks: @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.2" + rev: "v0.8.5" hooks: - id: ruff-format - id: ruff @@ -34,7 +34,7 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.3.3 + - prettier@3.4.2 - "@prettier/plugin-xml@3.4.1" - repo: meta hooks: diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index c17fb4cb..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,320 +0,0 @@ -# Changelog - -## 1.22 - -- Allow Sphinx explicitly to write in parallel. -- Fixed crash when documenting ParamSpecArgs - -## 1.21.7 - -- Fixed a bug where if a class has an attribute and a constructor argument with the same name, the constructor argument - type would be rendered incorrectly (issue 308) - -- Fixed napoleon handling of numpy docstrings with no specified return type. - -## 1.21.6 - -- Fix a `Field list ends without a blank line` warning (issue 305). - -## 1.21.5 - -- More robust determination of rtype location / fix issue 302 - -## 1.21.4 - -- Improvements to the location of the return type - -## 1.21.3 - -- Use format_annotation to render class attribute type annotations - -## 1.21.2 - -- Fix overloads support - -## 1.21.1 - -- Fix spacing between `:rtype:` and directives - -## 1.21 - -- Handle types from types module -- If module is \_io, use io instead -- Put rtype before examples or usage section -- Remove redundant return type for attributes -- Handle collections.abc.Callable as well as typing.Callable -- Put Literal args in code blocks - -## 1.20.2 - -- Fix Optional role to be data. - -## 1.20.1 - -- Fixed default options not displaying for parameters without type hints. - -## 1.20 - -- Use hatchling instead of setuptools -- Add support for typing.ParamSpec -- Allow star prefixes for parameter names in docstring - -## 1.19.2 - -- Fix incorrect domain used for collections.abc.Callable. - -## 1.19.1 - -- Fix bug for recursive type alias. - -## 1.19.0 - -- Support for CPython 3.11, no longer adds `Optional` when the argument is default per - [recommendation from PEP-484](https://github.com/tox-dev/sphinx-autodoc-typehints/pull/247). - -## 1.18.3 - -- Support and require `nptyping>=2.1.2` - -## 1.18.2 - -- Support and require `nptyping>=2.1.1` - -## 1.18.1 - -- Fix mocked module import not working when used as guarded import - -## 1.18.0 - -- Support and require `nptyping>=2` -- Handle `UnionType` - -## 1.17.1 - -- Mark it as requiring `nptyping<2` - -## 1.17.0 - -- Add `typehints_use_rtype` option -- Handles `TypeError` when getting source code via inspect - -## 1.16.0 - -- Add support for type subscriptions with multiple elements, where one or more elements are tuples; e.g., - `nptyping.NDArray[(Any, ...), nptyping.Float]` -- Fix bug for arbitrary types accepting singleton subscriptions; e.g., `nptyping.Float[64]` -- Resolve forward references -- Expand and better handle `TypeVar` -- Add intershpinx reference link for `...` to `Ellipsis` (as is just an alias) - -## 1.15.3 - -- Prevents reaching inner blocks that contains `if TYPE_CHECKING` - -## 1.15.2 - -- Log a warning instead of crashing when a type guard import fails to resolve -- When resolving type guard imports if the target module does not have source code (such is the case for C-extension - modules) do nothing instead of crashing - -## 1.15.1 - -- Fix `fully_qualified` should be `typehints_fully_qualified` - -## 1.15.0 - -- Resolve type guard imports before evaluating annotations for objects -- Remove `set_type_checking_flag` flag as this is now done by default -- Fix crash when the `inspect` module returns an invalid python syntax source -- Made formatting function configurable using the option `typehints_formatter` - -## 1.14.1 - -- Fixed `normalize_source_lines()` messing with the indentation of methods with decorators that have parameters starting - with `def`. -- Handle `ValueError` or `TypeError` being raised when signature of an object cannot be determined -- Fix `KeyError` being thrown when argument is not documented (e.g. `cls` argument for class methods, and `self` for - methods) - -## 1.14.0 - -- Added `typehints_defaults` config option allowing to automatically annotate parameter defaults. - -## 1.13.1 - -- Fixed `NewType` inserts a reference as first argument instead of a string - -## 1.13.0 - -- Dropped Python 3.6 support -- Python 3.10 support -- Normalize async functions properly -- Allow py310 style annotations (PEP-563) - -## 1.12.0 - -- Dropped Python 3.5 support -- Added the simplify_optional_unions config option (PR by tillhainbach) -- Fixed indentation of multiline strings (PR by Yuxin Wu) - -## 1.11.1 - -- Changed formatting of `None` to point to the Python stdlib docs (PR by Dominic Davis-Foster) -- Updated special dataclass handling (PR by Lihu Ben-Ezri-Ravin) - -## 1.11.0 - -- Dropped support for Sphinx \< 3.0 -- Added support for alternative parameter names (`arg`, `argument`, `parameter`) -- Fixed import path for Signature (PR by Matthew Treinish) -- Fixed `TypeError` when formatting a parametrized `typing.IO` annotation -- Fixed data class displaying a return type in its `__init__()` method - -## 1.10.3 - -- Fixed `TypeError` (or wrong rendered class name) when an annotation is a generic class that has a `name` property - -## 1.10.2 - -- Fixed inner classes missing their parent class name(s) when rendered - -## 1.10.1 - -- Fixed `KeyError` when encountering mocked annotations (`autodoc_mock_imports`) - -## 1.10.0 - -- Rewrote the annotation formatting logic (fixes Python 3.5.2 compatibility regressions and an `AttributeError` - regression introduced in v1.9.0) -- Fixed decorator classes not being processed as classes - -## 1.9.0 - -- Added support for [typing_extensions](https://pypi.org/project/typing-extensions/) -- Added the `typehints_document_rtype` option (PR by Simon-Martin Schröder) -- Fixed metaclasses as annotations causing `TypeError` -- Fixed rendering of `typing.Literal` -- Fixed OSError when generating docs for SQLAlchemy mapped classes -- Fixed unparametrized generic classes being rendered with their type parameters (e.g. `Dict[~KT, ~VT]`) - -## 1.8.0 - -- Fixed regression which caused `TypeError` or `OSError` when trying to set annotations due to PR #87 -- Fixed unintentional mangling of annotation type names -- Added proper `:py:data` targets for `NoReturn`, `ClassVar` and `Tuple` -- Added support for inline type comments (like `(int, str) -> None`) (PR by Bernát Gábor) -- Use the native AST parser for type comment support on Python 3.8+ - -## 1.7.0 - -- Dropped support for Python 3.4 -- Fixed unwrapped local functions causing errors (PR by Kimiyuki Onaka) -- Fixed `AttributeError` when documenting the `__init__()` method of a data class -- Added support for type hint comments (PR by Markus Unterwaditzer) -- Added flag for rendering classes with their fully qualified names (PR by Holly Becker) - -## 1.6.0 - -- Fixed `TypeError` when formatting annotations from a class that inherits from a concrete generic type (report and - tests by bpeake-illuscio) -- Added support for `typing_extensions.Protocol` (PR by Ian Good) -- Added support for `typing.NewType` (PR by George Leslie-Waksman) - -## 1.5.2 - -- Emit a warning instead of crashing when an unresolvable forward reference is encountered in type annotations - -## 1.5.1 - -- Fixed escape characters in parameter default values getting lost during signature processing -- Replaced use of the `config-inited` event (which inadvertently required Sphinx 1.8) with the `builder-inited` event - -## 1.5.0 - -- The setting of the `typing.TYPECHECKING` flag is now configurable using the `set_type_checking_flag` option - -## 1.4.0 - -- The extension now sets `typing.TYPECHECKING` to `True` during setup to include conditional imports which may be used - in type annotations -- Fixed parameters with trailing underscores (PR by Daniel Knell) -- Fixed KeyError with private methods (PR by Benito Palacios Sánchez) -- Fixed deprecation warning about the use of formatargspec (PR by Y. Somda) -- The minimum Sphinx version is now v1.7.0 - -## 1.3.1 - -- Fixed rendering of generic types outside the typing module (thanks to Tim Poterba for the PR) - -## 1.3.0 - -- Fixed crash when processing docstrings from nested classes (thanks to dilyanpalauzov for the fix) -- Added support for Python 3.7 -- Dropped support for Python 3.5.0 and 3.5.1 - -## 1.2.5 - -- Ensured that `:rtype:` doesn\'t get joined with a paragraph of text (thanks to Bruce Merry for the PR) - -## 1.2.4 - -- Removed support for `backports.typing` as it has been removed from the PyPI -- Fixed first parameter being cut out from class methods and static methods (thanks to Josiah Wolf Oberholtzer for the - PR) - -## 1.2.3 - -- Fixed `process_signature()` clobbering any explicitly overridden signatures from the docstring - -## 1.2.2 - -- Explicitly prefix `:class:`, `:mod:` et al with `:py:`, in case `py` is not the default domain of the project (thanks - Monty Taylor) - -## 1.2.1 - -- Fixed ``ValueError` when``getargspec()\`\` encounters a built-in function -- Fixed `AttributeError` when `Any` is combined with another type in a `Union` (thanks Davis Kirkendall) - -## 1.2.0 - -- Fixed compatibility with Python 3.6 and 3.5.3 -- Fixed `NameError` when processing signatures of wrapped functions with type hints -- Fixed handling of slotted classes with no `__init__()` method -- Fixed Sphinx warning about parallel reads -- Fixed return type being added to class docstring from its `__init__()` method (thanks to Manuel Krebber for the patch) -- Fixed return type hints of `@property` methods being omitted (thanks to pknight for the patch) -- Added a test suite (thanks Manuel Krebber) - -## 1.1.0 - -- Added proper support for `typing.Tuple` (pull request by Manuel Krebber) - -## 1.0.6 - -- Fixed wrong placement of `:rtype:` if a multi-line `:param:` or a `:returns:` is used - -## 1.0.5 - -- Fixed coroutine functions\' signatures not being processed when using sphinxcontrib-asyncio - -## 1.0.4 - -- Fixed compatibility with Sphinx 1.4 - -## 1.0.3 - -- Fixed \"self\" parameter not being removed from exception class constructor signatures -- Fixed process_signature() erroneously removing the first argument of a static method - -## 1.0.2 - -- Fixed exception classes not being processed like normal classes - -## 1.0.1 - -- Fixed errors caused by forward references not being looked up with the right globals - -## 1.0.0 - -- Initial release diff --git a/pyproject.toml b/pyproject.toml index 5c8cbfea..2b2459b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ build-backend = "hatchling.build" requires = [ "hatch-vcs>=0.4", - "hatchling>=1.25", + "hatchling>=1.27", ] [project] @@ -41,22 +41,19 @@ dynamic = [ "version", ] dependencies = [ - "sphinx>=8.0.2", + "sphinx>=8.1.3", ] optional-dependencies.docs = [ "furo>=2024.8.6", ] -optional-dependencies.numpy = [ - "nptyping>=2.5", -] optional-dependencies.testing = [ "covdefaults>=2.3", - "coverage>=7.6.1", + "coverage>=7.6.10", "defusedxml>=0.7.1", # required by sphinx.testing - "diff-cover>=9.1.1", - "pytest>=8.3.2", - "pytest-cov>=5", - "sphobjinv>=2.3.1.1", + "diff-cover>=9.2.1", + "pytest>=8.3.4", + "pytest-cov>=6", + "sphobjinv>=2.3.1.2", "typing-extensions>=4.12.2", ] urls.Changelog = "https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md" @@ -69,7 +66,6 @@ build.hooks.vcs.version-file = "src/sphinx_autodoc_typehints/version.py" version.source = "vcs" [tool.ruff] -target-version = "py310" line-length = 120 format.preview = true format.docstring-code-line-length = 100 @@ -78,7 +74,6 @@ lint.select = [ "ALL", ] lint.ignore = [ - "ANN101", # no type annotation for self "ANN401", # allow Any as type annotation "COM812", # Conflict with formatter "CPY", # No copyright statements @@ -135,7 +130,7 @@ paths.source = [ "*/src", "*\\src", ] -report.fail_under = 85 +report.fail_under = 88 report.omit = [ ] run.parallel = true diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index fd5db7a4..dedfdbeb 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -64,7 +64,7 @@ def get_annotation_module(annotation: Any) -> str: return "builtins" if _get_types_type(annotation) is not None: return "types" - is_new_type = sys.version_info >= (3, 10) and isinstance(annotation, NewType) + is_new_type = isinstance(annotation, NewType) if ( is_new_type or isinstance(annotation, TypeVar) @@ -157,7 +157,7 @@ def get_annotation_args(annotation: Any, module: str, class_name: str) -> tuple[ def format_internal_tuple(t: tuple[Any, ...], config: Config) -> str: - # An annotation can be a tuple, e.g., for nptyping: + # An annotation can be a tuple, e.g., for numpy.typing: # In this case, format_annotation receives: # This solution should hopefully be general for *any* type that allows tuples in annotations fmt = [format_annotation(a, config) for a in t] @@ -233,7 +233,7 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL # Some types require special handling if full_name == "typing.NewType": args_format = f"\\(``{annotation.__name__}``, {{}})" - role = "class" if sys.version_info >= (3, 10) else "func" + role = "class" elif full_name in {"typing.TypeVar", "typing.ParamSpec"}: params = {k: getattr(annotation, f"__{k}__") for k in ("bound", "covariant", "contravariant")} params = {k: v for k, v in params.items() if v} @@ -423,8 +423,7 @@ def _future_annotations_imported(obj: Any) -> bool: # Make sure that annotations is imported from __future__ - defined in cpython/Lib/__future__.py # annotations become strings at runtime - future_annotations = 0x100000 if sys.version_info[0:2] == (3, 7) else 0x1000000 - return bool(annotations_.compiler_flag == future_annotations) + return bool(annotations_.compiler_flag == 0x1000000) # pragma: no cover # noqa: PLR2004 def get_all_type_hints( diff --git a/tests/conftest.py b/tests/conftest.py index a50bc0d5..91874ad6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,10 +4,9 @@ import shutil import sys from pathlib import Path -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING import pytest -from sphinx.testing.path import path from sphobjinv import Inventory if TYPE_CHECKING: @@ -32,12 +31,11 @@ def inv(pytestconfig: Config) -> Inventory: @pytest.fixture(autouse=True) -def _remove_sphinx_projects(sphinx_test_tempdir: path) -> None: +def _remove_sphinx_projects(sphinx_test_tempdir: Path) -> None: # Remove any directory which appears to be a Sphinx project from # the temporary directory area. # See https://github.com/sphinx-doc/sphinx/issues/4040 - roots_path = Path(sphinx_test_tempdir) - for entry in roots_path.iterdir(): + for entry in sphinx_test_tempdir.iterdir(): try: if entry.is_dir() and Path(entry, "_build").exists(): shutil.rmtree(str(entry)) @@ -46,13 +44,13 @@ def _remove_sphinx_projects(sphinx_test_tempdir: path) -> None: @pytest.fixture -def rootdir() -> path: - return path(str(Path(__file__).parent) or ".").abspath() / "roots" +def rootdir() -> Path: + return Path(str(Path(__file__).parent) or ".").absolute() / "roots" -def pytest_ignore_collect(path: Any, config: Config) -> bool | None: # noqa: ARG001 +def pytest_ignore_collect(collection_path: Path, config: Config) -> bool | None: # noqa: ARG001 version_re = re.compile(r"_py(\d)(\d)\.py$") - match = version_re.search(path.basename) + match = version_re.search(collection_path.name) if match: version = tuple(int(x) for x in match.groups()) if sys.version_info < version: diff --git a/tests/roots/test-resolve-typing-guard/demo_typing_guard.py b/tests/roots/test-resolve-typing-guard/demo_typing_guard.py index 0c42d6ee..e1c352b7 100644 --- a/tests/roots/test-resolve-typing-guard/demo_typing_guard.py +++ b/tests/roots/test-resolve-typing-guard/demo_typing_guard.py @@ -10,8 +10,8 @@ from demo_typing_guard_dummy import AnotherClass if TYPE_CHECKING: + from collections.abc import Sequence from decimal import Decimal - from typing import Sequence # noqa: UP035 from demo_typing_guard_dummy import Literal # guarded by another `if TYPE_CHECKING` in demo_typing_guard_dummy diff --git a/tests/test_integration.py b/tests/test_integration.py index 93aa1e52..2c5d352c 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1239,8 +1239,6 @@ def has_newtype(param: W) -> W: :members: """ -LT_PY310 = sys.version_info < (3, 10) - @expected( """ @@ -1467,8 +1465,6 @@ def test_integration( result = (Path(app.srcdir) / "_build/text/index.txt").read_text() expected = val.EXPECTED - if LT_PY310: - expected = expected.replace("NewType", "NewType()") try: assert result.strip() == dedent(expected).strip() except Exception: diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index acc5aca2..92c96f45 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -1,10 +1,10 @@ from __future__ import annotations -import collections.abc import re import sys import types import typing +from collections.abc import Callable, Mapping from functools import cmp_to_key from io import StringIO from pathlib import Path @@ -14,15 +14,11 @@ IO, Any, AnyStr, - Callable, Dict, Generic, List, - Mapping, - Match, NewType, Optional, - Pattern, Tuple, Type, TypeVar, @@ -50,11 +46,6 @@ from sphinx.testing.util import SphinxTestApp from sphobjinv import Inventory -try: - import nptyping -except ImportError: - nptyping = None # type: ignore[assignment] - T = TypeVar("T") U_co = TypeVar("U_co", covariant=True) V_contra = TypeVar("V_contra", contravariant=True) @@ -114,25 +105,8 @@ def method(self: T) -> T: # type: ignore[empty-body] ... -PY310_PLUS = sys.version_info >= (3, 10) PY312_PLUS = sys.version_info >= (3, 12) -if sys.version_info >= (3, 9): # noqa: UP036 - AbcCallable = collections.abc.Callable # type: ignore[type-arg] -else: - # We could also set AbcCallable = typing.Callable and x fail the tests that - # use AbcCallable when in versions less than 3.9. - class MyGenericAlias(typing._VariadicGenericAlias, _root=True): # noqa: SLF001 - def __getitem__(self, params): # noqa: ANN001, ANN204 - result = super().__getitem__(params) - # Make a copy so we don't change the name of a cached annotation - result = result.copy_with(result.__args__) - result.__module__ = "collections.abc" - return result - - AbcCallable = MyGenericAlias(collections.abc.Callable, (), special=True) - AbcCallable.__module__ = "collections.abc" - @pytest.mark.parametrize( ("annotation", "module", "class_name", "args"), @@ -151,20 +125,22 @@ def __getitem__(self, params): # noqa: ANN001, ANN204 pytest.param(Tuple, "typing", "Tuple", (), id="Tuple"), # noqa: UP006 pytest.param(Tuple[str, int], "typing", "Tuple", (str, int), id="Tuple_parametrized"), # noqa: UP006 pytest.param(Union[str, int], "typing", "Union", (str, int), id="Union"), # noqa: UP007 - pytest.param(Callable, "typing", "Callable", (), id="Callable"), - pytest.param(Callable[..., str], "typing", "Callable", (..., str), id="Callable_returntype"), - pytest.param(Callable[[int, str], str], "typing", "Callable", (int, str, str), id="Callable_all_types"), + pytest.param(Callable, "collections.abc", "Callable", (), id="Callable"), + pytest.param(Callable[..., str], "collections.abc", "Callable", (..., str), id="Callable_returntype"), + pytest.param( + Callable[[int, str], str], "collections.abc", "Callable", (int, str, str), id="Callable_all_types" + ), pytest.param( - AbcCallable[[int, str], str], # type: ignore[type-arg,misc,valid-type] + Callable[[int, str], str], "collections.abc", "Callable", (int, str, str), id="collections.abc.Callable_all_types", ), - pytest.param(Pattern, "typing", "Pattern", (), id="Pattern"), - pytest.param(Pattern[str], "typing", "Pattern", (str,), id="Pattern_parametrized"), - pytest.param(Match, "typing", "Match", (), id="Match"), - pytest.param(Match[str], "typing", "Match", (str,), id="Match_parametrized"), + pytest.param(re.Pattern, "re", "Pattern", (), id="Pattern"), + pytest.param(re.Pattern[str], "re", "Pattern", (str,), id="Pattern_parametrized"), + pytest.param(re.Match, "re", "Match", (), id="Match"), + pytest.param(re.Match[str], "re", "Match", (str,), id="Match_parametrized"), pytest.param(IO, "typing", "IO", (), id="IO"), pytest.param(W, "typing", "NewType", (str,), id="W"), pytest.param(P, "typing", "ParamSpec", (), id="P"), @@ -196,33 +172,33 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t pytest.param(ModuleType, ":py:class:`~types.ModuleType`", id="ModuleType"), pytest.param(type(None), ":py:obj:`None`", id="type None"), pytest.param(type, ":py:class:`type`", id="type"), - pytest.param(collections.abc.Callable, ":py:class:`~collections.abc.Callable`", id="abc-Callable"), + pytest.param(Callable, ":py:class:`~collections.abc.Callable`", id="abc-Callable"), pytest.param(Type, ":py:class:`~typing.Type`", id="typing-Type"), # noqa: UP006 pytest.param(Type[A], rf":py:class:`~typing.Type`\ \[:py:class:`~{__name__}.A`]", id="typing-A"), # noqa: UP006 pytest.param(Any, ":py:data:`~typing.Any`", id="Any"), pytest.param(AnyStr, ":py:data:`~typing.AnyStr`", id="AnyStr"), pytest.param(Generic[T], r":py:class:`~typing.Generic`\ \[:py:class:`~typing.TypeVar`\ \(``T``)]", id="Generic"), - pytest.param(Mapping, ":py:class:`~typing.Mapping`", id="Mapping"), + pytest.param(Mapping, ":py:class:`~collections.abc.Mapping`", id="Mapping"), pytest.param( Mapping[T, int], # type: ignore[valid-type] - r":py:class:`~typing.Mapping`\ \[:py:class:`~typing.TypeVar`\ \(``T``), :py:class:`int`]", + r":py:class:`~collections.abc.Mapping`\ \[:py:class:`~typing.TypeVar`\ \(``T``), :py:class:`int`]", id="Mapping-T-int", ), pytest.param( Mapping[str, V_contra], # type: ignore[valid-type] - r":py:class:`~typing.Mapping`\ \[:py:class:`str`, :py:class:`~typing.TypeVar`\ \(" + r":py:class:`~collections.abc.Mapping`\ \[:py:class:`str`, :py:class:`~typing.TypeVar`\ \(" "``V_contra``, contravariant=True)]", id="Mapping-T-int-contra", ), pytest.param( Mapping[T, U_co], # type: ignore[valid-type] - r":py:class:`~typing.Mapping`\ \[:py:class:`~typing.TypeVar`\ \(``T``), " + r":py:class:`~collections.abc.Mapping`\ \[:py:class:`~typing.TypeVar`\ \(``T``), " r":py:class:`~typing.TypeVar`\ \(``U_co``, covariant=True)]", id="Mapping-T-int-co", ), pytest.param( Mapping[str, bool], - r":py:class:`~typing.Mapping`\ \[:py:class:`str`, :py:class:`bool`]", + r":py:class:`~collections.abc.Mapping`\ \[:py:class:`str`, :py:class:`bool`]", id="Mapping-str-bool", ), pytest.param(Dict, ":py:class:`~typing.Dict`", id="Dict"), # noqa: UP006 @@ -295,40 +271,40 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", id="Optional-Union-str-bool", ), - pytest.param(Callable, ":py:data:`~typing.Callable`", id="Callable"), + pytest.param(Callable, ":py:class:`~collections.abc.Callable`", id="Callable"), pytest.param( Callable[..., int], - r":py:data:`~typing.Callable`\ \[:py:data:`...`, :py:class:`int`]", + r":py:class:`~collections.abc.Callable`\ \[:py:data:`...`, :py:class:`int`]", id="Callable-Ellipsis-int", ), pytest.param( Callable[[int], int], - r":py:data:`~typing.Callable`\ \[\[:py:class:`int`], :py:class:`int`]", + r":py:class:`~collections.abc.Callable`\ \[\[:py:class:`int`], :py:class:`int`]", id="Callable-int-int", ), pytest.param( Callable[[int, str], bool], - r":py:data:`~typing.Callable`\ \[\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", + r":py:class:`~collections.abc.Callable`\ \[\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", id="Callable-int-str-bool", ), pytest.param( Callable[[int, str], None], - r":py:data:`~typing.Callable`\ \[\[:py:class:`int`, :py:class:`str`], :py:obj:`None`]", + r":py:class:`~collections.abc.Callable`\ \[\[:py:class:`int`, :py:class:`str`], :py:obj:`None`]", id="Callable-int-str", ), pytest.param( Callable[[T], T], - r":py:data:`~typing.Callable`\ \[\[:py:class:`~typing.TypeVar`\ \(``T``)]," + r":py:class:`~collections.abc.Callable`\ \[\[:py:class:`~typing.TypeVar`\ \(``T``)]," r" :py:class:`~typing.TypeVar`\ \(``T``)]", id="Callable-T-T", ), pytest.param( - AbcCallable[[int, str], bool], # type: ignore[valid-type,misc,type-arg] + Callable[[int, str], bool], r":py:class:`~collections.abc.Callable`\ \[\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", - id="AbcCallable-int-str-bool", + id="Callable-int-str-bool", ), - pytest.param(Pattern, ":py:class:`~typing.Pattern`", id="Pattern"), - pytest.param(Pattern[str], r":py:class:`~typing.Pattern`\ \[:py:class:`str`]", id="Pattern-str"), + pytest.param(re.Pattern, ":py:class:`~re.Pattern`", id="Pattern"), + pytest.param(re.Pattern[str], r":py:class:`~re.Pattern`\ \[:py:class:`str`]", id="Pattern-str"), pytest.param(IO, ":py:class:`~typing.IO`", id="IO"), pytest.param(IO[str], r":py:class:`~typing.IO`\ \[:py:class:`str`]", id="IO-str"), pytest.param(Metaclass, f":py:class:`~{__name__}.Metaclass`", id="Metaclass"), @@ -339,7 +315,7 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t pytest.param(D, f":py:class:`~{__name__}.D`", id="D"), pytest.param(E, f":py:class:`~{__name__}.E`", id="E"), pytest.param(E[int], rf":py:class:`~{__name__}.E`\ \[:py:class:`int`]", id="E-int"), - pytest.param(W, rf":py:{'class' if PY310_PLUS else 'func'}:`~typing.NewType`\ \(``W``, :py:class:`str`)", id="W"), + pytest.param(W, r":py:class:`~typing.NewType`\ \(``W``, :py:class:`str`)", id="W"), pytest.param(T, r":py:class:`~typing.TypeVar`\ \(``T``)", id="T"), pytest.param(U_co, r":py:class:`~typing.TypeVar`\ \(``U_co``, covariant=True)", id="U-co"), pytest.param(V_contra, r":py:class:`~typing.TypeVar`\ \(``V_contra``, contravariant=True)", id="V-contra"), @@ -389,58 +365,6 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t ), ] -if nptyping is not None: - _CASES.extend( - [ # Internal tuple with following additional type cannot be flattened (specific to nptyping?) - # These cases will fail if nptyping restructures its internal module hierarchy - pytest.param( - nptyping.NDArray[nptyping.Shape["*"], nptyping.Float], - ( - ":py:class:`~nptyping.ndarray.NDArray`\\ \\[:py:class:`~nptyping.base_meta_classes.Shape`\\ \\[*], " - ":py:class:`~numpy.float64`]" - ), - id="NDArray-star-float", - ), - pytest.param( - nptyping.NDArray[nptyping.Shape["64"], nptyping.Float], - ( - ":py:class:`~nptyping.ndarray.NDArray`\\ \\[:py:class:`~nptyping.base_meta_classes.Shape`\\ \\[64]," - " :py:class:`~numpy.float64`]" - ), - id="NDArray-64-float", - ), - pytest.param( - nptyping.NDArray[nptyping.Shape["*, *"], nptyping.Float], - ( - ":py:class:`~nptyping.ndarray.NDArray`\\ \\[:py:class:`~nptyping.base_meta_classes.Shape`\\ \\[*, " - "*], :py:class:`~numpy.float64`]" - ), - id="NDArray-star-star-float", - ), - pytest.param( - nptyping.NDArray[nptyping.Shape["*, ..."], nptyping.Float], - ":py:class:`~nptyping.ndarray.NDArray`\\ \\[:py:data:`~typing.Any`, :py:class:`~numpy.float64`]", - id="NDArray-star-Ellipsis-float", - ), - pytest.param( - nptyping.NDArray[nptyping.Shape["*, 3"], nptyping.Float], - ( - ":py:class:`~nptyping.ndarray.NDArray`\\ \\[:py:class:`~nptyping.base_meta_classes.Shape`\\ \\[*, 3" - "], :py:class:`~numpy.float64`]" - ), - id="NDArray-star-3-float", - ), - pytest.param( - nptyping.NDArray[nptyping.Shape["3, ..."], nptyping.Float], - ( - ":py:class:`~nptyping.ndarray.NDArray`\\ \\[:py:class:`~nptyping.base_meta_classes.Shape`\\ \\[3, " - "...], :py:class:`~numpy.float64`]" - ), - id="NDArray-3-Ellipsis-float", - ), - ], - ) - @pytest.mark.parametrize(("annotation", "expected_result"), _CASES) def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str) -> None: @@ -476,9 +400,9 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str assert format_annotation(annotation, conf) == expected_result_not_simplified # Test with the "fully_qualified" flag turned on - if "typing" in expected_result or "nptyping" in expected_result or __name__ in expected_result: + if "typing" in expected_result or __name__ in expected_result: expected_result = expected_result.replace("~typing", "typing") - expected_result = expected_result.replace("~nptyping", "nptyping") + expected_result = expected_result.replace("~collections.abc", "collections.abc") expected_result = expected_result.replace("~numpy", "numpy") expected_result = expected_result.replace("~" + __name__, __name__) conf = create_autospec( @@ -515,7 +439,6 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str ("Union[int, float] | str", ":py:class:`int` | :py:class:`float` | :py:class:`str`"), ], ) -@pytest.mark.skipif(not PY310_PLUS, reason="| union doesn't work before py310") def test_always_use_bars_union(annotation: str, expected_result: str) -> None: conf = create_autospec(Config, always_use_bars_union=True) result = format_annotation(eval(annotation), conf) # noqa: S307 @@ -630,8 +553,6 @@ class dummy_module.DataClass(x) def maybe_fix_py310(expected_contents: str) -> str: if sys.version_info >= (3, 11): return expected_contents - if not PY310_PLUS: - return expected_contents.replace('"', "") for old, new in [ ('"str" | "None"', '"Optional"["str"]'), diff --git a/tox.ini b/tox.ini index 7c952483..eef0f288 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] requires = - tox>=4.2 - tox-uv>=1.11.3 + tox>=4.23.2 + tox-uv>=1.16.2 env_list = fix 3.13 @@ -38,15 +38,15 @@ commands = description = format the code base to adhere to our styles, and complain about what we cannot do automatically skip_install = true deps = - pre-commit-uv>=4.1.1 + pre-commit-uv>=4.1.4 commands = pre-commit run --all-files --show-diff-on-failure [testenv:type] description = run type check on code base deps = - mypy==1.11.2 - types-docutils>=0.21.0.20240907 + mypy==1.14 + types-docutils>=0.21.0.20241128 commands = mypy src mypy tests @@ -55,9 +55,9 @@ commands = description = check that the long description is valid skip_install = true deps = - check-wheel-contents>=0.6 - twine>=5.1.1 - uv>=0.4.10 + check-wheel-contents>=0.6.1 + twine>=6.0.1 + uv>=0.5.11 commands = uv build --sdist --wheel --out-dir {env_tmp_dir} . twine check {env_tmp_dir}{/}* diff --git a/whitelist.txt b/whitelist.txt index 0e748bdc..e69de29b 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -1,90 +0,0 @@ -addnodes -arg1 -arg2 -ast3 -astext -autodoc -autouse -backfill -conf -contravariant -Coroutine -cpython -csv -dedent -delattr -desc -dirname -docnames -docstrings -Documenter -docutils -dunder -eval -exc -fget -fmt -fn -formatter -func -getitem -getmodule -getsource -globals -idx -inited -inv -isdatadescriptor -isfunction -iterdir -kwonlyargs -libs -lineno -lru -metaclass -ModuleType -multiline -newtype -numpy -nptyping -param -parametrized -params -parsers -pathlib -pos -prepend -py310 -pydata -pytestconfig -qualname -rootdir -rst -rtype -runtime -setitem -sig -signode -skipif -sph -sphobjinv -srcdir -stdlib -stmt -stringify -subclasses -supertype -tagname -tempdir -testroot -textwrap -toctree -typ -typehint -typehints -unittest -unlink -unresolvable -util -utils -vararg From aceb328cd1487f54a73aa4c8f488a39c2feb3da6 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Thu, 16 Jan 2025 12:25:06 +0100 Subject: [PATCH 07/56] Fix roles for `types` module (#516) Fixes #498 Also apparently the emitted role for FunctionType used to be wrong, so fixes that as well. --- src/sphinx_autodoc_typehints/__init__.py | 20 ++++++++++++++++++-- tests/test_sphinx_autodoc_typehints.py | 10 +++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index dedfdbeb..e6215926 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -36,7 +36,23 @@ from sphinx.ext.autodoc import Options _LOGGER = logging.getLogger(__name__) -_PYDATA_ANNOTATIONS = {"Any", "AnyStr", "Callable", "ClassVar", "Literal", "NoReturn", "Optional", "Tuple", "Union"} +_PYDATA_ANNOTS_TYPING = {"Any", "AnyStr", "Callable", "ClassVar", "Literal", "NoReturn", "Optional", "Tuple", "Union"} +_PYDATA_ANNOTS_TYPES = { + *("AsyncGeneratorType", "BuiltinFunctionType", "BuiltinMethodType"), + *("CellType", "ClassMethodDescriptorType", "CoroutineType"), + "EllipsisType", + *("FrameType", "FunctionType"), + *("GeneratorType", "GetSetDescriptorType"), + "LambdaType", + *("MemberDescriptorType", "MethodDescriptorType", "MethodType", "MethodWrapperType"), + # NoneType is special, but included here for completeness' sake + *("NoneType", "NotImplementedType"), + "WrapperDescriptorType", +} +_PYDATA_ANNOTATIONS = { + *(("typing", n) for n in _PYDATA_ANNOTS_TYPING), + *(("types", n) for n in _PYDATA_ANNOTS_TYPES), +} # types has a bunch of things like ModuleType where ModuleType.__module__ is # "builtins" and ModuleType.__name__ is "module", so we have to check for this. @@ -219,7 +235,7 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL full_name = f"{module}.{class_name}" if module != "builtins" else class_name fully_qualified: bool = getattr(config, "typehints_fully_qualified", False) prefix = "" if fully_qualified or full_name == class_name else "~" - role = "data" if module == "typing" and class_name in _PYDATA_ANNOTATIONS else "class" + role = "data" if (module, class_name) in _PYDATA_ANNOTATIONS else "class" args_format = "\\[{}]" formatted_args: str | None = "" diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index 92c96f45..65c3f6cf 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -9,7 +9,7 @@ from io import StringIO from pathlib import Path from textwrap import dedent, indent -from types import FunctionType, ModuleType +from types import EllipsisType, FrameType, FunctionType, ModuleType, NotImplementedType, TracebackType from typing import ( # noqa: UP035 IO, Any, @@ -168,8 +168,12 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t pytest.param(str, ":py:class:`str`", id="str"), pytest.param(int, ":py:class:`int`", id="int"), pytest.param(StringIO, ":py:class:`~io.StringIO`", id="StringIO"), - pytest.param(FunctionType, ":py:class:`~types.FunctionType`", id="FunctionType"), + pytest.param(EllipsisType, ":py:data:`~types.EllipsisType`", id="EllipsisType"), + pytest.param(FunctionType, ":py:data:`~types.FunctionType`", id="FunctionType"), + pytest.param(FrameType, ":py:data:`~types.FrameType`", id="FrameType"), pytest.param(ModuleType, ":py:class:`~types.ModuleType`", id="ModuleType"), + pytest.param(NotImplementedType, ":py:data:`~types.NotImplementedType`", id="NotImplementedType"), + pytest.param(TracebackType, ":py:class:`~types.TracebackType`", id="TracebackType"), pytest.param(type(None), ":py:obj:`None`", id="type None"), pytest.param(type, ":py:class:`type`", id="type"), pytest.param(Callable, ":py:class:`~collections.abc.Callable`", id="abc-Callable"), @@ -414,7 +418,7 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str assert format_annotation(annotation, conf) == expected_result # Test for the correct role (class vs data) using the official Sphinx inventory - if "typing" in expected_result: + if any(modname in expected_result for modname in ("typing", "types")): m = re.match(r"^:py:(?Pclass|data|func):`~(?P[^`]+)`", result) assert m, "No match" name = m.group("name") From 1fda047b296bdf16ba13ecd7d403105b6d21c002 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Thu, 16 Jan 2025 12:41:50 +0100 Subject: [PATCH 08/56] Update Ruff to 0.9.1 (#517) And clean up noqa usage in tests --- .pre-commit-config.yaml | 4 +- pyproject.toml | 3 ++ tests/test_integration.py | 14 +++--- tests/test_sphinx_autodoc_typehints.py | 66 +++++++++++++------------- 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 04461d8b..9b52ba03 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.30.0 + rev: "0.30.0" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.5" + rev: "v0.9.1" hooks: - id: ruff-format - id: ruff diff --git a/pyproject.toml b/pyproject.toml index 2b2459b8..d60d302b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,6 +93,9 @@ lint.per-file-ignores."tests/**/*.py" = [ "PLR2004", # Magic value used in comparison, consider replacing with a constant variable "S101", # asserts allowed in tests "S603", # `subprocess` call: check for execution of untrusted input + "UP006", # we test for old List/Tuple syntax + "UP007", # we test for old Union syntax + "UP045", # we test for old Optional syntax ] lint.isort = { known-first-party = [ "sphinx_autodoc_typehints", diff --git a/tests/test_integration.py b/tests/test_integration.py index 2c5d352c..c0d218b6 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -148,10 +148,10 @@ class Class: :param z: baz """ - def __init__(self, x: bool, y: int, z: Optional[str] = None) -> None: # noqa: UP007 + def __init__(self, x: bool, y: int, z: Optional[str] = None) -> None: pass - def a_method(self, x: bool, y: int, z: Optional[str] = None) -> str: # noqa: UP007 + def a_method(self, x: bool, y: int, z: Optional[str] = None) -> str: """ Method docstring. @@ -182,7 +182,7 @@ def __magic_custom_method__(self, x: str) -> str: # noqa: PLW3201 """ @classmethod - def a_classmethod(cls, x: bool, y: int, z: Optional[str] = None) -> str: # noqa: UP007 + def a_classmethod(cls, x: bool, y: int, z: Optional[str] = None) -> str: """ Classmethod docstring. @@ -192,7 +192,7 @@ def a_classmethod(cls, x: bool, y: int, z: Optional[str] = None) -> str: # noqa """ @staticmethod - def a_staticmethod(x: bool, y: int, z: Optional[str] = None) -> str: # noqa: UP007 + def a_staticmethod(x: bool, y: int, z: Optional[str] = None) -> str: """ Staticmethod docstring. @@ -270,7 +270,7 @@ def __init__(self, message: str) -> None: bytes """, ) -def function(x: bool, y: int, z_: Optional[str] = None) -> str: # noqa: UP007 +def function(x: bool, y: int, z_: Optional[str] = None) -> str: """ Function docstring. @@ -647,7 +647,7 @@ def func_with_overload(a: str, b: str) -> None: ... "None" """, ) -def func_with_overload(a: Union[int, str], b: Union[int, str]) -> None: # noqa: UP007 +def func_with_overload(a: Union[int, str], b: Union[int, str]) -> None: """ f does the thing. The arguments can either be ints or strings but they must both have the same type. @@ -675,7 +675,7 @@ class mod.TestClassAttributeDocs class TestClassAttributeDocs: """A class""" - code: Optional[CodeType] # noqa: UP007 + code: Optional[CodeType] """An attribute""" diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index 65c3f6cf..6edcfcf1 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -63,9 +63,9 @@ # Mypy does not support recursive type aliases, but # other type checkers do. -RecList = Union[int, List["RecList"]] # noqa: UP006, UP007 -MutualRecA = Union[bool, List["MutualRecB"]] # noqa: UP006, UP007 -MutualRecB = Union[str, List["MutualRecA"]] # noqa: UP006, UP007 +RecList = Union[int, List["RecList"]] +MutualRecA = Union[bool, List["MutualRecB"]] +MutualRecB = Union[str, List["MutualRecA"]] class A: @@ -119,12 +119,12 @@ def method(self: T) -> T: # type: ignore[empty-body] pytest.param(types.CoroutineType, "types", "CoroutineType", (), id="CoroutineType"), pytest.param(Any, "typing", "Any", (), id="Any"), pytest.param(AnyStr, "typing", "AnyStr", (), id="AnyStr"), - pytest.param(Dict, "typing", "Dict", (), id="Dict"), # noqa: UP006 - pytest.param(Dict[str, int], "typing", "Dict", (str, int), id="Dict_parametrized"), # noqa: UP006 - pytest.param(Dict[T, int], "typing", "Dict", (T, int), id="Dict_typevar"), # type: ignore[valid-type] # noqa: UP006 - pytest.param(Tuple, "typing", "Tuple", (), id="Tuple"), # noqa: UP006 - pytest.param(Tuple[str, int], "typing", "Tuple", (str, int), id="Tuple_parametrized"), # noqa: UP006 - pytest.param(Union[str, int], "typing", "Union", (str, int), id="Union"), # noqa: UP007 + pytest.param(Dict, "typing", "Dict", (), id="Dict"), + pytest.param(Dict[str, int], "typing", "Dict", (str, int), id="Dict_parametrized"), + pytest.param(Dict[T, int], "typing", "Dict", (T, int), id="Dict_typevar"), # type: ignore[valid-type] + pytest.param(Tuple, "typing", "Tuple", (), id="Tuple"), + pytest.param(Tuple[str, int], "typing", "Tuple", (str, int), id="Tuple_parametrized"), + pytest.param(Union[str, int], "typing", "Union", (str, int), id="Union"), pytest.param(Callable, "collections.abc", "Callable", (), id="Callable"), pytest.param(Callable[..., str], "collections.abc", "Callable", (..., str), id="Callable_returntype"), pytest.param( @@ -177,8 +177,8 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t pytest.param(type(None), ":py:obj:`None`", id="type None"), pytest.param(type, ":py:class:`type`", id="type"), pytest.param(Callable, ":py:class:`~collections.abc.Callable`", id="abc-Callable"), - pytest.param(Type, ":py:class:`~typing.Type`", id="typing-Type"), # noqa: UP006 - pytest.param(Type[A], rf":py:class:`~typing.Type`\ \[:py:class:`~{__name__}.A`]", id="typing-A"), # noqa: UP006 + pytest.param(Type, ":py:class:`~typing.Type`", id="typing-Type"), + pytest.param(Type[A], rf":py:class:`~typing.Type`\ \[:py:class:`~{__name__}.A`]", id="typing-A"), pytest.param(Any, ":py:data:`~typing.Any`", id="Any"), pytest.param(AnyStr, ":py:data:`~typing.AnyStr`", id="AnyStr"), pytest.param(Generic[T], r":py:class:`~typing.Generic`\ \[:py:class:`~typing.TypeVar`\ \(``T``)]", id="Generic"), @@ -205,73 +205,73 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t r":py:class:`~collections.abc.Mapping`\ \[:py:class:`str`, :py:class:`bool`]", id="Mapping-str-bool", ), - pytest.param(Dict, ":py:class:`~typing.Dict`", id="Dict"), # noqa: UP006 + pytest.param(Dict, ":py:class:`~typing.Dict`", id="Dict"), pytest.param( - Dict[T, int], # type: ignore[valid-type] # noqa: UP006 + Dict[T, int], # type: ignore[valid-type] r":py:class:`~typing.Dict`\ \[:py:class:`~typing.TypeVar`\ \(``T``), :py:class:`int`]", id="Dict-T-int", ), pytest.param( - Dict[str, V_contra], # type: ignore[valid-type] # noqa: UP006 + Dict[str, V_contra], # type: ignore[valid-type] r":py:class:`~typing.Dict`\ \[:py:class:`str`, :py:class:`~typing.TypeVar`\ \(``V_contra``, " r"contravariant=True)]", id="Dict-T-int-contra", ), pytest.param( - Dict[T, U_co], # type: ignore[valid-type] # noqa: UP006 + Dict[T, U_co], # type: ignore[valid-type] r":py:class:`~typing.Dict`\ \[:py:class:`~typing.TypeVar`\ \(``T``)," r" :py:class:`~typing.TypeVar`\ \(``U_co``, covariant=True)]", id="Dict-T-int-co", ), pytest.param( - Dict[str, bool], # noqa: UP006 + Dict[str, bool], r":py:class:`~typing.Dict`\ \[:py:class:`str`, :py:class:`bool`]", - id="Dict-str-bool", # noqa: RUF100, UP006 + id="Dict-str-bool", ), - pytest.param(Tuple, ":py:data:`~typing.Tuple`", id="Tuple"), # noqa: UP006 + pytest.param(Tuple, ":py:data:`~typing.Tuple`", id="Tuple"), pytest.param( - Tuple[str, bool], # noqa: UP006 + Tuple[str, bool], r":py:data:`~typing.Tuple`\ \[:py:class:`str`, :py:class:`bool`]", - id="Tuple-str-bool", # noqa: RUF100, UP006 + id="Tuple-str-bool", ), pytest.param( - Tuple[int, int, int], # noqa: UP006 + Tuple[int, int, int], r":py:data:`~typing.Tuple`\ \[:py:class:`int`, :py:class:`int`, :py:class:`int`]", id="Tuple-int-int-int", ), pytest.param( - Tuple[str, ...], # noqa: UP006 + Tuple[str, ...], r":py:data:`~typing.Tuple`\ \[:py:class:`str`, :py:data:`...`]", id="Tuple-str-Ellipsis", ), pytest.param(Union, ":py:data:`~typing.Union`", id="Union"), pytest.param( - Union[str, bool], # noqa: UP007 + Union[str, bool], r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`]", id="Union-str-bool", ), pytest.param( - Union[str, bool, None], # noqa: UP007 + Union[str, bool, None], r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", id="Union-str-bool-None", ), pytest.param( - Union[str, Any], # noqa: UP007 + Union[str, Any], r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:data:`~typing.Any`]", id="Union-str-Any", ), pytest.param( - Optional[str], # noqa: UP007 + Optional[str], r":py:data:`~typing.Optional`\ \[:py:class:`str`]", id="Optional-str", ), pytest.param( - Union[str, None], # noqa: UP007 + Union[str, None], r":py:data:`~typing.Optional`\ \[:py:class:`str`]", id="Optional-str-None", ), pytest.param( - Optional[str | bool], # noqa: UP007 + Optional[str | bool], r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", id="Optional-Union-str-bool", ), @@ -345,17 +345,17 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t pytest.param(P_bound, r":py:class:`~typing.ParamSpec`\ \(``P_bound``, bound= :py:class:`str`)", id="P-bound"), # ## These test for correct internal tuple rendering, even if not all are valid Tuple types # Zero-length tuple remains - pytest.param(Tuple[()], ":py:data:`~typing.Tuple`", id="Tuple-p"), # noqa: UP006 + pytest.param(Tuple[()], ":py:data:`~typing.Tuple`", id="Tuple-p"), # Internal single tuple with simple types is flattened in the output - pytest.param(Tuple[int,], r":py:data:`~typing.Tuple`\ \[:py:class:`int`]", id="Tuple-p-int"), # noqa: UP006 + pytest.param(Tuple[int,], r":py:data:`~typing.Tuple`\ \[:py:class:`int`]", id="Tuple-p-int"), pytest.param( - Tuple[int, int], # noqa: UP006 + Tuple[int, int], r":py:data:`~typing.Tuple`\ \[:py:class:`int`, :py:class:`int`]", - id="Tuple-p-int-int", # noqa: RUF100, UP006 + id="Tuple-p-int-int", ), # Ellipsis in single tuple also gets flattened pytest.param( - Tuple[int, ...], # noqa: UP006 + Tuple[int, ...], r":py:data:`~typing.Tuple`\ \[:py:class:`int`, :py:data:`...`]", id="Tuple-p-Ellipsis", ), From 02ce7667fdb0ee79c256999a149ff5442fc1a7b0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 16 Jan 2025 06:06:50 -0800 Subject: [PATCH 09/56] [pre-commit.ci] pre-commit autoupdate (#515) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/python-jsonschema/check-jsonschema: 0.30.0 → 0.31.0](https://github.com/python-jsonschema/check-jsonschema/compare/0.30.0...0.31.0) * Update .pre-commit-config.yaml Co-authored-by: Philipp A. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Hood Chatham Co-authored-by: Philipp A. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b52ba03..c21124b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.30.0" + rev: "0.31.0" hooks: - id: check-github-workflows args: ["--verbose"] From 5a6f7982ded90fe04324ae0812deb29b37f1922c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 08:08:33 -0800 Subject: [PATCH 10/56] [pre-commit.ci] pre-commit autoupdate (#518) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.1 → v0.9.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.1...v0.9.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c21124b1..b6f93951 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.1" + rev: "v0.9.2" hooks: - id: ruff-format - id: ruff From da5feae414692e2394ce5df2f1bceec34e694abb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Jan 2025 08:03:23 -0800 Subject: [PATCH 11/56] Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4 (#519) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.3 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/v1.12.3...v1.12.4) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index df296276..86624162 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,6 +43,6 @@ jobs: name: ${{ env.dists-artifact-name }} path: dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.3 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: attestations: true From bfa7f43c11676907003e88366566d233ce49e70a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 10:02:30 -0800 Subject: [PATCH 12/56] [pre-commit.ci] pre-commit autoupdate (#520) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/codespell-project/codespell: v2.3.0 → v2.4.0](https://github.com/codespell-project/codespell/compare/v2.3.0...v2.4.0) - [github.com/tox-dev/tox-ini-fmt: 1.4.1 → 1.5.0](https://github.com/tox-dev/tox-ini-fmt/compare/1.4.1...1.5.0) - [github.com/astral-sh/ruff-pre-commit: v0.9.2 → v0.9.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.2...v0.9.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b6f93951..025ae0ac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,12 +10,12 @@ repos: - id: check-github-workflows args: ["--verbose"] - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.0 hooks: - id: codespell additional_dependencies: ["tomli>=2.2.1"] - repo: https://github.com/tox-dev/tox-ini-fmt - rev: "1.4.1" + rev: "1.5.0" hooks: - id: tox-ini-fmt args: ["-p", "fix"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.2" + rev: "v0.9.3" hooks: - id: ruff-format - id: ruff From fd427dc0772f0cc35bc3494e0d7c939c98ceac9b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 16:11:36 -0800 Subject: [PATCH 13/56] [pre-commit.ci] pre-commit autoupdate (#521) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.31.0 → 0.31.1](https://github.com/python-jsonschema/check-jsonschema/compare/0.31.0...0.31.1) - [github.com/codespell-project/codespell: v2.4.0 → v2.4.1](https://github.com/codespell-project/codespell/compare/v2.4.0...v2.4.1) - [github.com/astral-sh/ruff-pre-commit: v0.9.3 → v0.9.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.3...v0.9.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 025ae0ac..040957bf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,12 +5,12 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.31.0" + rev: "0.31.1" hooks: - id: check-github-workflows args: ["--verbose"] - repo: https://github.com/codespell-project/codespell - rev: v2.4.0 + rev: v2.4.1 hooks: - id: codespell additional_dependencies: ["tomli>=2.2.1"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.3" + rev: "v0.9.4" hooks: - id: ruff-format - id: ruff From 6ffdf92ffce85c9dce596faf682d457dc6429c70 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 10:48:11 -0800 Subject: [PATCH 14/56] [pre-commit.ci] pre-commit autoupdate (#522) 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: v0.9.4 → v0.9.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.4...v0.9.6) - [github.com/rbubley/mirrors-prettier: v3.4.2 → v3.5.0](https://github.com/rbubley/mirrors-prettier/compare/v3.4.2...v3.5.0) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- tests/test_sphinx_autodoc_typehints.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 040957bf..b4e653f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,13 +24,13 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.4" + rev: "v0.9.6" hooks: - id: ruff-format - id: ruff args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier - rev: "v3.4.2" # Use the sha / tag you want to point at + rev: "v3.5.0" # Use the sha / tag you want to point at hooks: - id: prettier additional_dependencies: diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index 6edcfcf1..31e077ec 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -98,10 +98,10 @@ class Metaclass(type): ... class HintedMethods: @classmethod - def from_magic(cls: type[T]) -> T: # type: ignore[empty-body] + def from_magic(cls) -> typing_extensions.Self: # type: ignore[empty-body] ... - def method(self: T) -> T: # type: ignore[empty-body] + def method(self) -> typing_extensions.Self: # type: ignore[empty-body] ... From f09eb89ba1fe60a71b1bb0711a82e5bb8476b5ea Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 14:04:35 -0800 Subject: [PATCH 15/56] [pre-commit.ci] pre-commit autoupdate (#524) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/rbubley/mirrors-prettier: v3.5.0 → v3.5.1](https://github.com/rbubley/mirrors-prettier/compare/v3.5.0...v3.5.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4e653f3..aaf240a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -30,7 +30,7 @@ repos: - id: ruff args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier - rev: "v3.5.0" # Use the sha / tag you want to point at + rev: "v3.5.1" # Use the sha / tag you want to point at hooks: - id: prettier additional_dependencies: From ca5fcc0f37461601ce0b2682cc96ce16d028febc Mon Sep 17 00:00:00 2001 From: bart <61748872+b-kamphorst@users.noreply.github.com> Date: Wed, 19 Feb 2025 16:37:41 +0100 Subject: [PATCH 16/56] Support Sphinx 8.2.0 - drop 3.10 support because Sphinx does (#525) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(deps): update dependency sphinx to v8.2.0 * refactor: patch stringify_annotation with arbitrary *args and **kwargs * fix: derive annotation for TypeAliasForwardRef from its name attribute TypeAliasForwardRef.__repr__ was changed in sphinx v8.2.0 to not only yield the name, but also the class name. * test: update warning message "unpickable" was renamed to "unpickleable" in sphinx v8.2.0 * feat: respect configuration option python_display_short_literal_types https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-python_display_short_literal_types * Sphinx 8.2 drops 3.10 support Signed-off-by: Bernát Gábor --------- Signed-off-by: Bernát Gábor Co-authored-by: Bernát Gábor --- .github/workflows/check.yaml | 1 - .pre-commit-config.yaml | 2 +- pyproject.toml | 11 ++-- src/sphinx_autodoc_typehints/__init__.py | 31 ++++++---- .../attributes_patch.py | 4 +- tests/conftest.py | 5 +- tests/test_integration.py | 56 ++++++++++++++++++- tests/test_sphinx_autodoc_typehints.py | 13 +---- tox.ini | 11 ++-- 9 files changed, 91 insertions(+), 43 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 08004343..c028c36c 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -22,7 +22,6 @@ jobs: - "3.13" - "3.12" - "3.11" - - "3.10" - type - dev - pkg_meta diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aaf240a8..fb3e0997 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.4.2 + - prettier@3.5.1 - "@prettier/plugin-xml@3.4.1" - repo: meta hooks: diff --git a/pyproject.toml b/pyproject.toml index d60d302b..1fbdbdbc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ maintainers = [ authors = [ { name = "Bernát Gábor", email = "gaborjbernat@gmail.com" }, ] -requires-python = ">=3.10" +requires-python = ">=3.11" classifiers = [ "Development Status :: 5 - Production/Stable", "Framework :: Sphinx :: Extension", @@ -31,7 +31,6 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", @@ -41,16 +40,16 @@ dynamic = [ "version", ] dependencies = [ - "sphinx>=8.1.3", + "sphinx>=8.2", ] optional-dependencies.docs = [ "furo>=2024.8.6", ] optional-dependencies.testing = [ "covdefaults>=2.3", - "coverage>=7.6.10", + "coverage>=7.6.12", "defusedxml>=0.7.1", # required by sphinx.testing - "diff-cover>=9.2.1", + "diff-cover>=9.2.3", "pytest>=8.3.4", "pytest-cov>=6", "sphobjinv>=2.3.1.2", @@ -142,7 +141,7 @@ run.plugins = [ ] [tool.mypy] -python_version = "3.10" +python_version = "3.11" strict = true exclude = "^(.*/roots/.*)|(tests/test_integration.*.py)$" overrides = [ diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index e6215926..432fdf46 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -172,11 +172,11 @@ def get_annotation_args(annotation: Any, module: str, class_name: str) -> tuple[ return () if len(result) == 1 and result[0] == () else result # type: ignore[misc] -def format_internal_tuple(t: tuple[Any, ...], config: Config) -> str: +def format_internal_tuple(t: tuple[Any, ...], config: Config, *, short_literals: bool = False) -> str: # An annotation can be a tuple, e.g., for numpy.typing: # In this case, format_annotation receives: # This solution should hopefully be general for *any* type that allows tuples in annotations - fmt = [format_annotation(a, config) for a in t] + fmt = [format_annotation(a, config, short_literals=short_literals) for a in t] if len(fmt) == 0: return "()" if len(fmt) == 1: @@ -196,12 +196,13 @@ def fixup_module_name(config: Config, module: str) -> str: return module -def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PLR0911, PLR0912, PLR0915, PLR0914 +def format_annotation(annotation: Any, config: Config, *, short_literals: bool = False) -> str: # noqa: C901, PLR0911, PLR0912, PLR0915, PLR0914 """ Format the annotation. :param annotation: :param config: + :param short_literals: Render :py:class:`Literals` in PEP 604 style (``|``). :return: """ typehints_formatter: Callable[..., str] | None = getattr(config, "typehints_formatter", None) @@ -222,7 +223,7 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL return format_internal_tuple(annotation, config) if isinstance(annotation, TypeAliasForwardRef): - return str(annotation) + return annotation.name try: module = get_annotation_module(annotation) @@ -254,7 +255,7 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL params = {k: getattr(annotation, f"__{k}__") for k in ("bound", "covariant", "contravariant")} params = {k: v for k, v in params.items() if v} if "bound" in params: - params["bound"] = f" {format_annotation(params['bound'], config)}" + params["bound"] = f" {format_annotation(params['bound'], config, short_literals=short_literals)}" args_format = f"\\(``{annotation.__name__}``{', {}' if args else ''}" if params: args_format += "".join(f", {k}={v}" for k, v in params.items()) @@ -275,20 +276,22 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL args_format = f"\\[:py:data:`{prefix}typing.Union`\\[{{}}]]" args = tuple(x for x in args if x is not type(None)) elif full_name in {"typing.Callable", "collections.abc.Callable"} and args and args[0] is not ...: - fmt = [format_annotation(arg, config) for arg in args] + fmt = [format_annotation(arg, config, short_literals=short_literals) for arg in args] formatted_args = f"\\[\\[{', '.join(fmt[:-1])}], {fmt[-1]}]" elif full_name == "typing.Literal": + if short_literals: + return f"\\{' | '.join(f'``{arg!r}``' for arg in args)}" formatted_args = f"\\[{', '.join(f'``{arg!r}``' for arg in args)}]" elif is_bars_union: - return " | ".join([format_annotation(arg, config) for arg in args]) + return " | ".join([format_annotation(arg, config, short_literals=short_literals) for arg in args]) if args and not formatted_args: try: iter(args) except TypeError: - fmt = [format_annotation(args, config)] + fmt = [format_annotation(args, config, short_literals=short_literals)] else: - fmt = [format_annotation(arg, config) for arg in args] + fmt = [format_annotation(arg, config, short_literals=short_literals) for arg in args] formatted_args = args_format.format(", ".join(fmt)) escape = "\\ " if formatted_args else "" @@ -783,7 +786,10 @@ def _inject_signature( if annotation is None: type_annotation = f":type {arg_name}: " else: - formatted_annotation = add_type_css_class(format_annotation(annotation, app.config)) + short_literals = app.config.python_display_short_literal_types + formatted_annotation = add_type_css_class( + format_annotation(annotation, app.config, short_literals=short_literals) + ) type_annotation = f":type {arg_name}: {formatted_annotation}" if app.config.typehints_defaults: @@ -923,7 +929,10 @@ def _inject_rtype( # noqa: PLR0913, PLR0917 if not app.config.typehints_use_rtype and r.found_return and " -- " in lines[insert_index]: return - formatted_annotation = add_type_css_class(format_annotation(type_hints["return"], app.config)) + short_literals = app.config.python_display_short_literal_types + formatted_annotation = add_type_css_class( + format_annotation(type_hints["return"], app.config, short_literals=short_literals) + ) if r.found_param and insert_index < len(lines) and lines[insert_index].strip(): insert_index -= 1 diff --git a/src/sphinx_autodoc_typehints/attributes_patch.py b/src/sphinx_autodoc_typehints/attributes_patch.py index d038eae3..276dbd03 100644 --- a/src/sphinx_autodoc_typehints/attributes_patch.py +++ b/src/sphinx_autodoc_typehints/attributes_patch.py @@ -42,12 +42,12 @@ orig_handle_signature = PyAttribute.handle_signature -def _stringify_annotation(app: Sphinx, annotation: Any, mode: str = "") -> str: # noqa: ARG001 +def _stringify_annotation(app: Sphinx, annotation: Any, *args: Any, short_literals: bool = False, **kwargs: Any) -> str: # noqa: ARG001 # Format the annotation with sphinx-autodoc-typehints and inject our magic prefix to tell our patched # PyAttribute.handle_signature to treat it as rst. from . import format_annotation # noqa: PLC0415 - return TYPE_IS_RST_LABEL + format_annotation(annotation, app.config) + return TYPE_IS_RST_LABEL + format_annotation(annotation, app.config, short_literals=short_literals) def patch_attribute_documenter(app: Sphinx) -> None: diff --git a/tests/conftest.py b/tests/conftest.py index 91874ad6..19b09f38 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,6 +3,7 @@ import re import shutil import sys +from contextlib import suppress from pathlib import Path from typing import TYPE_CHECKING @@ -36,11 +37,9 @@ def _remove_sphinx_projects(sphinx_test_tempdir: Path) -> None: # the temporary directory area. # See https://github.com/sphinx-doc/sphinx/issues/4040 for entry in sphinx_test_tempdir.iterdir(): - try: + with suppress(PermissionError): if entry.is_dir() and Path(entry, "_build").exists(): shutil.rmtree(str(entry)) - except PermissionError: # noqa: PERF203 - pass @pytest.fixture diff --git a/tests/test_integration.py b/tests/test_integration.py index c0d218b6..900d585d 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -9,6 +9,7 @@ from typing import ( # no type comments TYPE_CHECKING, Any, + Literal, NewType, Optional, TypeVar, @@ -661,6 +662,59 @@ def func_with_overload(a: Union[int, str], b: Union[int, str]) -> None: """ +@expected( + """\ +mod.func_literals_long_format(a, b) + + A docstring. + + Parameters: + * **a** ("Literal"["'arg1'", "'arg2'"]) -- Argument that can + take either of two literal values. + + * **b** ("Literal"["'arg1'", "'arg2'"]) -- Argument that can + take either of two literal values. + + Return type: + "None" +""", +) +def func_literals_long_format(a: Literal["arg1", "arg2"], b: Literal["arg1", "arg2"]) -> None: + """ + A docstring. + + :param a: Argument that can take either of two literal values. + :param b: Argument that can take either of two literal values. + """ + + +@expected( + """\ +mod.func_literals_short_format(a, b) + + A docstring. + + Parameters: + * **a** ("'arg1'" | "'arg2'") -- Argument that can take either + of two literal values. + + * **b** ("'arg1'" | "'arg2'") -- Argument that can take either + of two literal values. + + Return type: + "None" +""", + python_display_short_literal_types=True, +) +def func_literals_short_format(a: Literal["arg1", "arg2"], b: Literal["arg1", "arg2"]) -> None: + """ + A docstring. + + :param a: Argument that can take either of two literal values. + :param b: Argument that can take either of two literal values. + """ + + @expected( """\ class mod.TestClassAttributeDocs @@ -1386,7 +1440,7 @@ def has_doctest1() -> None: Unformatted = TypeVar("Unformatted") -@warns("cannot cache unpickable configuration value: 'typehints_formatter'") +@warns("cannot cache unpickleable configuration value: 'typehints_formatter'") @expected( """ mod.typehints_formatter_applied_to_signature(param: Formatted) -> Formatted diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index 31e077ec..c0963c2c 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -554,17 +554,6 @@ class dummy_module.DataClass(x) assert contents == expected_contents -def maybe_fix_py310(expected_contents: str) -> str: - if sys.version_info >= (3, 11): - return expected_contents - - for old, new in [ - ('"str" | "None"', '"Optional"["str"]'), - ]: - expected_contents = expected_contents.replace(old, new) - return expected_contents - - @pytest.mark.sphinx("text", testroot="dummy") @patch("sphinx.writers.text.MAXWIDTH", 2000) def test_sphinx_output_future_annotations(app: SphinxTestApp, status: StringIO) -> None: @@ -595,7 +584,7 @@ def test_sphinx_output_future_annotations(app: SphinxTestApp, status: StringIO) "str" """ expected_contents = dedent(expected_contents) - expected_contents = maybe_fix_py310(dedent(expected_contents)) + expected_contents = dedent(expected_contents) assert contents == expected_contents diff --git a/tox.ini b/tox.ini index eef0f288..07cd05ab 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,12 @@ [tox] requires = - tox>=4.23.2 - tox-uv>=1.16.2 + tox>=4.24.1 + tox-uv>=1.24 env_list = fix 3.13 3.12 3.11 - 3.10 type pkg_meta skip_missing_interpreters = true @@ -45,7 +44,7 @@ commands = [testenv:type] description = run type check on code base deps = - mypy==1.14 + mypy==1.15 types-docutils>=0.21.0.20241128 commands = mypy src @@ -56,8 +55,8 @@ description = check that the long description is valid skip_install = true deps = check-wheel-contents>=0.6.1 - twine>=6.0.1 - uv>=0.5.11 + twine>=6.1 + uv>=0.6.1 commands = uv build --sdist --wheel --out-dir {env_tmp_dir} . twine check {env_tmp_dir}{/}* From 1f8bee57d54450864815c05aeeca8cace3da7b60 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 11:15:02 -0800 Subject: [PATCH 17/56] [pre-commit.ci] pre-commit autoupdate (#526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.31.1 → 0.31.2](https://github.com/python-jsonschema/check-jsonschema/compare/0.31.1...0.31.2) - [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.9.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7) - [github.com/rbubley/mirrors-prettier: v3.5.1 → v3.5.2](https://github.com/rbubley/mirrors-prettier/compare/v3.5.1...v3.5.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fb3e0997..05819626 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.31.1" + rev: "0.31.2" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,13 +24,13 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.6" + rev: "v0.9.7" hooks: - id: ruff-format - id: ruff args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier - rev: "v3.5.1" # Use the sha / tag you want to point at + rev: "v3.5.2" # Use the sha / tag you want to point at hooks: - id: prettier additional_dependencies: From bc75136b57edb2c7a2c75bac8a6d630eb949053a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 18:48:25 -0800 Subject: [PATCH 18/56] [pre-commit.ci] pre-commit autoupdate (#527) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/tox-dev/pyproject-fmt: v2.5.0 → v2.5.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.5.0...v2.5.1) - [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.9) - [github.com/rbubley/mirrors-prettier: v3.5.2 → v3.5.3](https://github.com/rbubley/mirrors-prettier/compare/v3.5.2...v3.5.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 05819626..9a39dd6e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,17 +20,17 @@ repos: - id: tox-ini-fmt args: ["-p", "fix"] - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.0" + rev: "v2.5.1" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.7" + rev: "v0.9.9" hooks: - id: ruff-format - id: ruff args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier - rev: "v3.5.2" # Use the sha / tag you want to point at + rev: "v3.5.3" # Use the sha / tag you want to point at hooks: - id: prettier additional_dependencies: From f4cd7d8eacac2fa8bc8fca91673bd0453c4f8b1d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 13:16:17 -0700 Subject: [PATCH 19/56] [pre-commit.ci] pre-commit autoupdate (#528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.31.2 → 0.31.3](https://github.com/python-jsonschema/check-jsonschema/compare/0.31.2...0.31.3) - [github.com/astral-sh/ruff-pre-commit: v0.9.9 → v0.9.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.9...v0.9.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9a39dd6e..51093ed3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.31.2" + rev: "0.31.3" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.9" + rev: "v0.9.10" hooks: - id: ruff-format - id: ruff From 5864a2502dafca9d2a363572aa3d1853743f00ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Gr=C3=B6nholm?= Date: Sun, 16 Mar 2025 21:05:19 +0200 Subject: [PATCH 20/56] Fixed broken changelog links (#530) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1fbdbdbc..37105b93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ optional-dependencies.testing = [ "sphobjinv>=2.3.1.2", "typing-extensions>=4.12.2", ] -urls.Changelog = "https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md" +urls.Changelog = "https://github.com/tox-dev/sphinx-autodoc-typehints/releases" urls.Homepage = "https://github.com/tox-dev/sphinx-autodoc-typehints" urls.Source = "https://github.com/tox-dev/sphinx-autodoc-typehints" urls.Tracker = "https://github.com/tox-dev/sphinx-autodoc-typehints/issues" From df9520ce98ca85325022d3fbe8be5737ce40a64d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 11:46:56 -0700 Subject: [PATCH 21/56] [pre-commit.ci] pre-commit autoupdate (#531) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.10 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.10...v0.11.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 51093ed3..0af920bd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.10" + rev: "v0.11.2" hooks: - id: ruff-format - id: ruff From 071901d3b2f9b75076febfd588de90c91204e32a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 12:37:02 -0700 Subject: [PATCH 22/56] [pre-commit.ci] pre-commit autoupdate (#534) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.31.3 → 0.32.1](https://github.com/python-jsonschema/check-jsonschema/compare/0.31.3...0.32.1) - [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0af920bd..14f8755c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.31.3" + rev: "0.32.1" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.2" + rev: "v0.11.4" hooks: - id: ruff-format - id: ruff From 9bc4b14f1c6d919c0154eb3b82c3ecf381b14f07 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 10:41:48 -0500 Subject: [PATCH 23/56] [pre-commit.ci] pre-commit autoupdate (#536) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.32.1 → 0.33.0](https://github.com/python-jsonschema/check-jsonschema/compare/0.32.1...0.33.0) - [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 14f8755c..d10536dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.32.1" + rev: "0.33.0" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.4" + rev: "v0.11.5" hooks: - id: ruff-format - id: ruff From e6ac91eedfc4a028b3c6ab4636c6670f6b36c9d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 11:38:53 -0500 Subject: [PATCH 24/56] Bump astral-sh/setup-uv from 5 to 6 (#541) Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5 to 6. - [Release notes](https://github.com/astral-sh/setup-uv/releases) - [Commits](https://github.com/astral-sh/setup-uv/compare/v5...v6) --- updated-dependencies: - dependency-name: astral-sh/setup-uv dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index c028c36c..f5461118 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -32,7 +32,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: enable-cache: true cache-dependency-glob: "pyproject.toml" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 86624162..4ff55fb3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: enable-cache: true cache-dependency-glob: "pyproject.toml" From a003dfcf8e445657942ca7289749643c833c8a34 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 25 Apr 2025 11:38:59 -0500 Subject: [PATCH 25/56] [pre-commit.ci] pre-commit autoupdate (#540) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.5 → v0.11.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.5...v0.11.6) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d10536dd..edf68afe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.5" + rev: "v0.11.6" hooks: - id: ruff-format - id: ruff From 05b79e3f2f310250c1adc0fbd7d0dd9c3e50f802 Mon Sep 17 00:00:00 2001 From: Nice Zombies Date: Fri, 25 Apr 2025 18:39:16 +0200 Subject: [PATCH 26/56] Fix issue #481 (#533) Co-authored-by: Wannes Boeykens Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/sphinx_autodoc_typehints/__init__.py | 17 ++++++++++++----- tests/test_integration_autodoc_type_aliases.py | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 432fdf46..4f20b973 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -10,14 +10,14 @@ import textwrap import types from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, AnyStr, ForwardRef, NewType, TypeVar, get_type_hints +from typing import TYPE_CHECKING, Any, AnyStr, ForwardRef, NewType, TypeVar, Union, get_type_hints from docutils import nodes from docutils.frontend import get_default_settings from sphinx.ext.autodoc.mock import mock from sphinx.parsers import RSTParser from sphinx.util import logging, rst -from sphinx.util.inspect import TypeAliasForwardRef, TypeAliasNamespace, stringify_signature +from sphinx.util.inspect import TypeAliasForwardRef, stringify_signature from sphinx.util.inspect import signature as sphinx_signature from ._parser import parse @@ -61,6 +61,11 @@ _TYPES_DICT[types.FunctionType] = "FunctionType" +class MyTypeAliasForwardRef(TypeAliasForwardRef): + def __or__(self, value: Any) -> Any: + return Union[self, value] # noqa: UP007 + + def _get_types_type(obj: Any) -> str | None: try: return _TYPES_DICT.get(obj) @@ -446,7 +451,7 @@ def _future_annotations_imported(obj: Any) -> bool: def get_all_type_hints( - autodoc_mock_imports: list[str], obj: Any, name: str, localns: TypeAliasNamespace + autodoc_mock_imports: list[str], obj: Any, name: str, localns: dict[Any, MyTypeAliasForwardRef] ) -> dict[str, Any]: result = _get_type_hint(autodoc_mock_imports, name, obj, localns) if not result: @@ -517,7 +522,9 @@ def _resolve_type_guarded_imports(autodoc_mock_imports: list[str], obj: Any) -> _execute_guarded_code(autodoc_mock_imports, obj, module_code) -def _get_type_hint(autodoc_mock_imports: list[str], name: str, obj: Any, localns: TypeAliasNamespace) -> dict[str, Any]: +def _get_type_hint( + autodoc_mock_imports: list[str], name: str, obj: Any, localns: dict[Any, MyTypeAliasForwardRef] +) -> dict[str, Any]: _resolve_type_guarded_imports(autodoc_mock_imports, obj) try: result = get_type_hints(obj, None, localns) @@ -689,7 +696,7 @@ def process_docstring( # noqa: PLR0913, PLR0917 except (ValueError, TypeError): signature = None - localns = TypeAliasNamespace(app.config["autodoc_type_aliases"]) + localns = {key: MyTypeAliasForwardRef(value) for key, value in app.config["autodoc_type_aliases"].items()} type_hints = get_all_type_hints(app.config.autodoc_mock_imports, obj, name, localns) app.config._annotation_globals = getattr(obj, "__globals__", {}) # noqa: SLF001 try: diff --git a/tests/test_integration_autodoc_type_aliases.py b/tests/test_integration_autodoc_type_aliases.py index 9d5a9511..f9640420 100644 --- a/tests/test_integration_autodoc_type_aliases.py +++ b/tests/test_integration_autodoc_type_aliases.py @@ -103,7 +103,7 @@ def g(s: AliasedClass) -> AliasedClass: Function docstring. Parameters: - * **x** (Array) -- foo + * **x** ("Optional"[Array]) -- foo * **y** ("Schema") -- boo @@ -115,7 +115,7 @@ def g(s: AliasedClass) -> AliasedClass: """, ) -def function(x: ArrayLike, y: Schema) -> str: +def function(x: ArrayLike | None, y: Schema) -> str: """ Function docstring. From 8a82cb8182dc8164f0098ee03936fec441ea9003 Mon Sep 17 00:00:00 2001 From: grayjk Date: Fri, 25 Apr 2025 12:43:45 -0400 Subject: [PATCH 27/56] Don't add :rtype: None (#538) --- README.md | 1 + src/sphinx_autodoc_typehints/__init__.py | 5 ++++- tests/test_integration.py | 13 +++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ddbf092..4da94768 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ The following configuration options are accepted: or `Optional[int]`) - `typehints_document_rtype` (default: `True`): If `False`, never add an `:rtype:` directive. If `True`, add the `:rtype:` directive if no existing `:rtype:` is found. +- `typehints_document_rtype_none` (default: `True`): If `False`, never add an `:rtype: None` directive. If `True`, add the `:rtype: None`. - `typehints_use_rtype` (default: `True`): Controls behavior when `typehints_document_rtype` is set to `True`. If `True`, document return type in the `:rtype:` directive. If `False`, document return type as part of the `:return:` directive, if present, otherwise fall back to using `:rtype:`. Use in conjunction with diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 4f20b973..7e1d994d 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -912,7 +912,7 @@ def get_insert_index(app: Sphinx, lines: list[str]) -> InsertIndexInfo | None: return InsertIndexInfo(insert_index=len(lines)) -def _inject_rtype( # noqa: PLR0913, PLR0917 +def _inject_rtype( # noqa: C901, PLR0913, PLR0917 type_hints: dict[str, Any], original_obj: Any, app: Sphinx, @@ -926,6 +926,8 @@ def _inject_rtype( # noqa: PLR0913, PLR0917 return if not app.config.typehints_document_rtype: return + if not app.config.typehints_document_rtype_none and type_hints["return"] is types.NoneType: + return r = get_insert_index(app, lines) if r is None: @@ -1011,6 +1013,7 @@ def setup(app: Sphinx) -> dict[str, bool]: app.add_config_value("always_document_param_types", False, "html") # noqa: FBT003 app.add_config_value("typehints_fully_qualified", False, "env") # noqa: FBT003 app.add_config_value("typehints_document_rtype", True, "env") # noqa: FBT003 + app.add_config_value("typehints_document_rtype_none", True, "env") # noqa: FBT003 app.add_config_value("typehints_use_rtype", True, "env") # noqa: FBT003 app.add_config_value("typehints_defaults", None, "env") app.add_config_value("simplify_optional_unions", True, "env") # noqa: FBT003 diff --git a/tests/test_integration.py b/tests/test_integration.py index 900d585d..2b53940c 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1319,6 +1319,19 @@ def typehints_use_signature(a: AsyncGenerator) -> AsyncGenerator: return a +@expected( + """ + mod.typehints_no_rtype_none() + + Do something. + + """, + typehints_document_rtype_none=False, +) +def typehints_no_rtype_none() -> None: + """Do something.""" + + prolog = """ .. |test_node_start| replace:: {test_node_start} """.format(test_node_start="test_start") From 830034f17cb14d51746b3b342c5352949abd0edc Mon Sep 17 00:00:00 2001 From: grayjk Date: Fri, 25 Apr 2025 12:48:10 -0400 Subject: [PATCH 28/56] Place rtype after directive (#537) --- src/sphinx_autodoc_typehints/__init__.py | 2 ++ tests/test_integration.py | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 7e1d994d..1394f734 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -906,6 +906,8 @@ def get_insert_index(app: Sphinx, lines: list[str]) -> InsertIndexInfo | None: continue line_no = node_line_no(child) at = max(line_no - 2, 0) if line_no else len(lines) + if lines[at - 1]: # skip if something on this line + break return InsertIndexInfo(insert_index=at, found_directive=True) # 5. Otherwise, insert at end diff --git a/tests/test_integration.py b/tests/test_integration.py index 2b53940c..9c1e3554 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1410,15 +1410,19 @@ def docstring_with_multiline_note_after_params_epilog_replace(param: int) -> Non """ mod.docstring_with_see_also() - Return type: - "str" + Test See also: more info at `_. + Return type: + "str" + """ ) def docstring_with_see_also() -> str: """ + Test + .. seealso:: more info at `_. """ return "" From 175cae3bfb2669812ca6c7a0ce685aba0ffe1e63 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:26:03 -0500 Subject: [PATCH 29/56] [pre-commit.ci] pre-commit autoupdate (#542) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.6 → v0.11.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.6...v0.11.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index edf68afe..0fae1d1f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.6" + rev: "v0.11.7" hooks: - id: ruff-format - id: ruff From 0e339b75557fe738b7b2273a0d61cd2399874e5b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 15:15:18 -0500 Subject: [PATCH 30/56] [pre-commit.ci] pre-commit autoupdate (#543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.7 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.7...v0.11.8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0fae1d1f..a78a831d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.7" + rev: "v0.11.8" hooks: - id: ruff-format - id: ruff From 16c1b2c3531583ed119139f9045361bab28f97e2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 09:49:44 -0500 Subject: [PATCH 31/56] [pre-commit.ci] pre-commit autoupdate (#544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a78a831d..f027026b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.8" + rev: "v0.11.9" hooks: - id: ruff-format - id: ruff From 0860f997b3a0668b3a42a6c4b969ec77bb89035e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 12:55:25 -0500 Subject: [PATCH 32/56] [pre-commit.ci] pre-commit autoupdate (#545) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.9 → v0.11.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.9...v0.11.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f027026b..c1ac3778 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.9" + rev: "v0.11.10" hooks: - id: ruff-format - id: ruff From 3c82b0daea54f61af483ef8011a69a3b72d74c17 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 09:39:51 -0500 Subject: [PATCH 33/56] [pre-commit.ci] pre-commit autoupdate (#546) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/tox-dev/pyproject-fmt: v2.5.1 → v2.6.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.5.1...v2.6.0) - [github.com/astral-sh/ruff-pre-commit: v0.11.10 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.10...v0.11.11) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1ac3778..febe2f68 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,11 +20,11 @@ repos: - id: tox-ini-fmt args: ["-p", "fix"] - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.1" + rev: "v2.6.0" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.10" + rev: "v0.11.11" hooks: - id: ruff-format - id: ruff From ec7e0ded00b6232103c16a29a4a0994ae5ecf017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Mon, 9 Jun 2025 08:37:20 -0500 Subject: [PATCH 34/56] Fix the CI failing due to type error (#548) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernát Gábor --- src/sphinx_autodoc_typehints/patches.py | 7 ++++--- tox.ini | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sphinx_autodoc_typehints/patches.py b/src/sphinx_autodoc_typehints/patches.py index 236b38dd..583ed498 100644 --- a/src/sphinx_autodoc_typehints/patches.py +++ b/src/sphinx_autodoc_typehints/patches.py @@ -103,7 +103,7 @@ def _patched_base_admonition_run(self: BaseAdmonition) -> Any: def _patched_text_indent(self: Text, *args: Any) -> Any: _, line = self.state_machine.get_source_and_line() - result = orig_text_indent(self, *args) + result = orig_text_indent(self, *args) # type: ignore[no-untyped-call] node = self.parent[-1] if node.tagname == "system_message": node = self.parent[-2] @@ -114,6 +114,7 @@ def _patched_text_indent(self: Text, *args: Any) -> Any: def _patched_body_doctest( self: Body, _match: None, _context: None, next_state: str | None ) -> tuple[list[Any], str | None, list[Any]]: + assert self.document.current_line is not None # noqa: S101 line = self.document.current_line + 1 data = "\n".join(self.state_machine.get_text_block()) n = nodes.doctest_block(data, data) @@ -128,9 +129,9 @@ def _patch_line_numbers() -> None: When the line numbers are missing, we have a hard time placing the :rtype:. """ - Text.indent = _patched_text_indent + Text.indent = _patched_text_indent # type: ignore[method-assign] BaseAdmonition.run = _patched_base_admonition_run # type: ignore[method-assign,assignment] - Body.doctest = _patched_body_doctest + Body.doctest = _patched_body_doctest # type: ignore[method-assign] def install_patches(app: Sphinx) -> None: diff --git a/tox.ini b/tox.ini index 07cd05ab..87924c5a 100644 --- a/tox.ini +++ b/tox.ini @@ -45,7 +45,7 @@ commands = description = run type check on code base deps = mypy==1.15 - types-docutils>=0.21.0.20241128 + types-docutils>=0.21.0.20250604 commands = mypy src mypy tests From 6df6e0c19a8ac6bb6975109c59bf2112b30fffdd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 20:59:41 -0700 Subject: [PATCH 35/56] [pre-commit.ci] pre-commit autoupdate (#547) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.11 → v0.11.13](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.11...v0.11.13) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index febe2f68..e3940ea3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.11" + rev: "v0.11.13" hooks: - id: ruff-format - id: ruff From a42ee47aee0d727c4243a873fb26fc209d06ea12 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Jun 2025 10:13:42 -0700 Subject: [PATCH 36/56] [pre-commit.ci] pre-commit autoupdate (#549) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.33.0 → 0.33.1](https://github.com/python-jsonschema/check-jsonschema/compare/0.33.0...0.33.1) - [github.com/astral-sh/ruff-pre-commit: v0.11.13 → v0.12.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.13...v0.12.1) - [github.com/rbubley/mirrors-prettier: v3.5.3 → v3.6.2](https://github.com/rbubley/mirrors-prettier/compare/v3.5.3...v3.6.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e3940ea3..c909c3c2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.33.0" + rev: "0.33.1" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,13 +24,13 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.13" + rev: "v0.12.1" hooks: - id: ruff-format - id: ruff args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier - rev: "v3.5.3" # Use the sha / tag you want to point at + rev: "v3.6.2" # Use the sha / tag you want to point at hooks: - id: prettier additional_dependencies: From fea5e1401e9b953fdc7675c8c11fda178592a762 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 10 Jul 2025 08:02:53 -0700 Subject: [PATCH 37/56] [pre-commit.ci] pre-commit autoupdate (#550) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.33.1 → 0.33.2](https://github.com/python-jsonschema/check-jsonschema/compare/0.33.1...0.33.2) - [github.com/astral-sh/ruff-pre-commit: v0.12.1 → v0.12.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.1...v0.12.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c909c3c2..7d519f83 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.33.1" + rev: "0.33.2" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.1" + rev: "v0.12.2" hooks: - id: ruff-format - id: ruff From 7f94014613d6074a2303c82e20510167fc622877 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Jul 2025 12:08:19 -0700 Subject: [PATCH 38/56] [pre-commit.ci] pre-commit autoupdate (#551) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.2 → v0.12.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.2...v0.12.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7d519f83..ea87c5d4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.2" + rev: "v0.12.3" hooks: - id: ruff-format - id: ruff From 9b3a613693e9ab521f23cc14f7df3d66fa607a32 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 12:57:35 -0700 Subject: [PATCH 39/56] [pre-commit.ci] pre-commit autoupdate (#552) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.3 → v0.12.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.3...v0.12.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ea87c5d4..ec580b65 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.3" + rev: "v0.12.4" hooks: - id: ruff-format - id: ruff From 3e9d99b83b0f6660cb90b1b0c02ebe1000814540 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 10:26:59 -0700 Subject: [PATCH 40/56] [pre-commit.ci] pre-commit autoupdate (#555) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.12.4 → v0.12.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.4...v0.12.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ec580b65..75a0cf2b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.4" + rev: "v0.12.5" hooks: - id: ruff-format - id: ruff From eab2076b806a56d14e20467827e2ea7548febf35 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Aug 2025 10:20:24 -0700 Subject: [PATCH 41/56] [pre-commit.ci] pre-commit autoupdate (#556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/tox-dev/tox-ini-fmt: 1.5.0 → 1.6.0](https://github.com/tox-dev/tox-ini-fmt/compare/1.5.0...1.6.0) - [github.com/astral-sh/ruff-pre-commit: v0.12.5 → v0.12.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.5...v0.12.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 75a0cf2b..beb8494c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,7 +15,7 @@ repos: - id: codespell additional_dependencies: ["tomli>=2.2.1"] - repo: https://github.com/tox-dev/tox-ini-fmt - rev: "1.5.0" + rev: "1.6.0" hooks: - id: tox-ini-fmt args: ["-p", "fix"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.5" + rev: "v0.12.7" hooks: - id: ruff-format - id: ruff From e9db2aaee73c6dfe466cde83ea502dc4c33c2fb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Aug 2025 07:08:39 -0700 Subject: [PATCH 42/56] Bump actions/download-artifact from 4 to 5 (#557) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4ff55fb3..f799d38d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -38,7 +38,7 @@ jobs: id-token: write steps: - name: Download all the dists - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: ${{ env.dists-artifact-name }} path: dist/ From 3f85e9bc1d600bf70b34c0da4998495d16fcbf7d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:30:52 -0700 Subject: [PATCH 43/56] [pre-commit.ci] pre-commit autoupdate (#558) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v5.0.0 → v6.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v5.0.0...v6.0.0) - [github.com/astral-sh/ruff-pre-commit: v0.12.7 → v0.12.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.7...v0.12.8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index beb8494c..0fa23e6b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v5.0.0 + rev: v6.0.0 hooks: - id: end-of-file-fixer - id: trailing-whitespace @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.7" + rev: "v0.12.8" hooks: - id: ruff-format - id: ruff From 8944f8553600d6155ac76bc4ccb893f229a53a88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:00:37 -0700 Subject: [PATCH 44/56] Bump actions/checkout from 4 to 5 (#559) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index f5461118..9da6aa70 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -28,7 +28,7 @@ jobs: steps: - name: Install OS dependencies run: sudo apt-get install graphviz -y - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 - name: Install the latest version of uv diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index f799d38d..6c2ff209 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -10,7 +10,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 - name: Install the latest version of uv From 7dd4a4e73f64840611aa5931050a52f418dea62c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Wed, 20 Aug 2025 06:36:06 -0700 Subject: [PATCH 45/56] Ignore type checker error breaking the CI (#561) --- src/sphinx_autodoc_typehints/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 1394f734..7a45ec14 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -877,7 +877,7 @@ def get_insert_index(app: Sphinx, lines: list[str]) -> InsertIndexInfo | None: # 3. Insert after the parameters. # To find the parameters, parse as a docutils tree. - settings = get_default_settings(RSTParser) + settings = get_default_settings(RSTParser) # type: ignore[arg-type] settings.env = app.env doc = parse("\n".join(lines), settings) From 80cc5f0165c8144f4ed45f92e28a3c2ad4526a57 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 16:54:21 +0000 Subject: [PATCH 46/56] [pre-commit.ci] pre-commit autoupdate (#560) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/python-jsonschema/check-jsonschema: 0.33.2 → 0.33.3](https://github.com/python-jsonschema/check-jsonschema/compare/0.33.2...0.33.3) - [github.com/astral-sh/ruff-pre-commit: v0.12.8 → v0.12.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.12.8...v0.12.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0fa23e6b..afaa9bdf 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.33.2" + rev: "0.33.3" hooks: - id: check-github-workflows args: ["--verbose"] @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.8" + rev: "v0.12.10" hooks: - id: ruff-format - id: ruff From 614310250f06c258839737b349fa0c81ff937999 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 07:45:39 -0700 Subject: [PATCH 47/56] [pre-commit.ci] pre-commit autoupdate (#563) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index afaa9bdf..0ab47e1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.10" + rev: "v0.12.11" hooks: - id: ruff-format - id: ruff From 876598b27d1cbcfb06e94f6c8c4dbeb6a5431451 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 07:14:36 -0700 Subject: [PATCH 48/56] Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0 (#564) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6c2ff209..4f5931ab 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,6 +43,6 @@ jobs: name: ${{ env.dists-artifact-name }} path: dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.13.0 with: attestations: true From a643e359b6743e6cf0f0ae9b4587e640dfc1c06c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 09:03:21 -0700 Subject: [PATCH 49/56] Bump pypa/gh-action-pypi-publish in /.github/workflows (#565) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> From a493b1118d9a09578054e77de85973888c0098d6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Sep 2025 10:35:32 -0700 Subject: [PATCH 50/56] [pre-commit.ci] pre-commit autoupdate (#566) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0ab47e1d..b6003315 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,7 +24,7 @@ repos: hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.11" + rev: "v0.12.12" hooks: - id: ruff-format - id: ruff From 5278aac37f12da32049b5ca8c76772e0008a557e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 10:10:52 -0700 Subject: [PATCH 51/56] [pre-commit.ci] pre-commit autoupdate (#567) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b6003315..1e2b6248 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/python-jsonschema/check-jsonschema - rev: "0.33.3" + rev: "0.34.0" hooks: - id: check-github-workflows args: ["--verbose"] @@ -20,11 +20,11 @@ repos: - id: tox-ini-fmt args: ["-p", "fix"] - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.6.0" + rev: "v2.7.0" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.12.12" + rev: "v0.13.3" hooks: - id: ruff-format - id: ruff From 22ccfb9ecdecf44695aefa8c20f483e67073c02b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Oct 2025 07:07:59 -0700 Subject: [PATCH 52/56] Bump astral-sh/setup-uv from 6 to 7 (#568) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/check.yaml | 2 +- .github/workflows/release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 9da6aa70..250c9b9d 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -32,7 +32,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "pyproject.toml" diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4f5931ab..a4c4f2f3 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -14,7 +14,7 @@ jobs: with: fetch-depth: 0 - name: Install the latest version of uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "pyproject.toml" From 239cc7b2e1f379799127236a118d6cf4fa8c11f5 Mon Sep 17 00:00:00 2001 From: Dan Fuchs <330402+fajpunk@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:08:31 -0500 Subject: [PATCH 53/56] Warning types and subtypes (#562) Co-authored-by: aeisenbarth <54448967+aeisenbarth@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- README.md | 7 ++++ src/sphinx_autodoc_typehints/__init__.py | 38 ++++++++++++++++---- tests/test_integration.py | 45 ++++++++++++++++++------ 3 files changed, 74 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 4da94768..384e226f 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,13 @@ The following configuration options are accepted: code or `None` to fall back to the default formatter. - `typehints_use_signature` (default: `False`): If `True`, typehints for parameters in the signature are shown. - `typehints_use_signature_return` (default: `False`): If `True`, return annotations in the signature are shown. +- `suppress_warnings`: sphinx-autodoc-typehints supports to suppress warning messages via Sphinx's `suppress_warnings`. It allows following additional warning types: + - `sphinx_autodoc_typehints` + - `sphinx_autodoc_typehints.comment` + - `sphinx_autodoc_typehints.forward_reference` + - `sphinx_autodoc_typehints.guarded_import` + - `sphinx_autodoc_typehints.local_function` + - `sphinx_autodoc_typehints.multiple_ast_nodes` ## How it works diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 7a45ec14..c5475694 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -407,7 +407,12 @@ def _get_formatted_annotation(annotation: TypeVar) -> TypeVar: elif what == "method": # bail if it is a local method as we cannot determine if first argument needs to be deleted or not if "" in obj.__qualname__ and not _is_dataclass(name, what, obj.__qualname__): - _LOGGER.warning('Cannot handle as a local function: "%s" (use @functools.wraps)', name) + _LOGGER.warning( + 'Cannot handle as a local function: "%s" (use @functools.wraps)', + name, + type="sphinx_autodoc_typehints", + subtype="local_function", + ) return None outer = inspect.getmodule(obj) for class_name in obj.__qualname__.split(".")[:-1]: @@ -500,7 +505,9 @@ def _execute_guarded_code(autodoc_mock_imports: list[str], obj: Any, module_code with mock(autodoc_mock_imports): exec(guarded_code, getattr(obj, "__globals__", obj.__dict__)) # noqa: S102 except Exception as exc: # noqa: BLE001 - _LOGGER.warning("Failed guarded type import with %r", exc) + _LOGGER.warning( + "Failed guarded type import with %r", exc, type="sphinx_autodoc_typehints", subtype="guarded_import" + ) def _resolve_type_guarded_imports(autodoc_mock_imports: list[str], obj: Any) -> None: @@ -536,7 +543,13 @@ def _get_type_hint( else: result = {} except NameError as exc: - _LOGGER.warning('Cannot resolve forward reference in type annotations of "%s": %s', name, exc) + _LOGGER.warning( + 'Cannot resolve forward reference in type annotations of "%s": %s', + name, + exc, + type="sphinx_autodoc_typehints", + subtype="forward_reference", + ) result = obj.__annotations__ return result @@ -554,7 +567,13 @@ def backfill_type_hints(obj: Any, name: str) -> dict[str, Any]: # noqa: C901, P def _one_child(module: Module) -> stmt | None: children = module.body # use the body to ignore type comments if len(children) != 1: - _LOGGER.warning('Did not get exactly one node from AST for "%s", got %s', name, len(children)) + _LOGGER.warning( + 'Did not get exactly one node from AST for "%s", got %s', + name, + len(children), + type="sphinx_autodoc_typehints", + subtype="multiple_ast_nodes", + ) return None return children[0] @@ -579,7 +598,12 @@ def _one_child(module: Module) -> stmt | None: try: comment_args_str, comment_returns = type_comment.split(" -> ") except ValueError: - _LOGGER.warning('Unparseable type hint comment for "%s": Expected to contain ` -> `', name) + _LOGGER.warning( + 'Unparseable type hint comment for "%s": Expected to contain ` -> `', + name, + type="sphinx_autodoc_typehints", + subtype="comment", + ) return {} rv = {} @@ -594,7 +618,9 @@ def _one_child(module: Module) -> stmt | None: comment_args.insert(0, None) # self/cls may be omitted in type comments, insert blank if len(args) != len(comment_args): - _LOGGER.warning('Not enough type comments found on "%s"', name) + _LOGGER.warning( + 'Not enough type comments found on "%s"', name, type="sphinx_autodoc_typehints", subtype="comment" + ) return rv for at, arg in enumerate(args): diff --git a/tests/test_integration.py b/tests/test_integration.py index 9c1e3554..02369f88 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -31,6 +31,28 @@ W = NewType("W", str) +@dataclass +class WarningInfo: + """Properties and assertion methods for warnings.""" + + regexp: str + type: str + + def assert_regexp(self, message: str) -> None: + regexp = self.regexp + msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {message!r}" + assert re.search(regexp, message), msg + + def assert_type(self, message: str) -> None: + expected = f"[{self.type}]" + msg = f"Warning did not contain type and subtype.\n Expected: {expected}\n Input: {message}" + assert expected in message, msg + + def assert_warning(self, message: str) -> None: + self.assert_regexp(message) + self.assert_type(message) + + def expected(expected: str, **options: dict[str, Any]) -> Callable[[T], T]: def dec(val: T) -> T: val.EXPECTED = expected @@ -40,9 +62,9 @@ def dec(val: T) -> T: return dec -def warns(pattern: str) -> Callable[[T], T]: +def warns(info: WarningInfo) -> Callable[[T], T]: def dec(val: T) -> T: - val.WARNING = pattern + val.WARNING = info return val return dec @@ -58,7 +80,7 @@ def wrapper(self) -> str: # noqa: ANN001 return wrapper -@warns("Cannot handle as a local function") +@warns(WarningInfo(regexp="Cannot handle as a local function", type="sphinx_autodoc_typehints.local_function")) @expected( """\ class mod.Class(x, y, z=None) @@ -330,7 +352,11 @@ def function_with_escaped_default(x: str = "\b"): # noqa: ANN201 """ -@warns("Cannot resolve forward reference in type annotations") +@warns( + WarningInfo( + regexp="Cannot resolve forward reference in type annotations", type="sphinx_autodoc_typehints.forward_reference" + ) +) @expected( """\ mod.function_with_unresolvable_annotation(x) @@ -1196,7 +1222,7 @@ def docstring_with_enum_list_after_params(param: int) -> None: """ -@warns("Definition list ends without a blank line") +@warns(WarningInfo(regexp="Definition list ends without a blank line", type="docutils")) @expected( """ mod.docstring_with_definition_list_after_params_no_blank_line(param) @@ -1457,7 +1483,7 @@ def has_doctest1() -> None: Unformatted = TypeVar("Unformatted") -@warns("cannot cache unpickleable configuration value: 'typehints_formatter'") +@warns(WarningInfo(regexp="cannot cache unpickleable configuration value: 'typehints_formatter'", type="config.cache")) @expected( """ mod.typehints_formatter_applied_to_signature(param: Formatted) -> Formatted @@ -1525,11 +1551,10 @@ def test_integration( app.build() assert "build succeeded" in status.getvalue() # Build succeeded - regexp = getattr(val, "WARNING", None) + warning_info: Union[WarningInfo, None] = getattr(val, "WARNING", None) value = warning.getvalue().strip() - if regexp: - msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" - assert re.search(regexp, value), msg + if warning_info: + warning_info.assert_warning(value) else: assert not value From ddac8c854ed70d6a69259e17245d5ac1706912b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Wed, 8 Oct 2025 16:37:16 -0700 Subject: [PATCH 54/56] Python 3.14 support (#569) --- .github/workflows/check.yaml | 6 ++- .github/workflows/release.yaml | 2 +- .pre-commit-config.yaml | 8 +-- README.md | 4 +- pyproject.toml | 20 +++---- src/sphinx_autodoc_typehints/__init__.py | 22 ++++++-- tests/test_integration.py | 24 ++++----- .../test_integration_autodoc_type_aliases.py | 4 +- tests/test_sphinx_autodoc_typehints.py | 54 +++++++++++++------ tox.ini | 18 ++++--- 10 files changed, 99 insertions(+), 63 deletions(-) diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 250c9b9d..61c26e88 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -19,6 +19,8 @@ jobs: fail-fast: false matrix: env: + - "3.14t" + - "3.14" - "3.13" - "3.12" - "3.11" @@ -38,9 +40,9 @@ jobs: cache-dependency-glob: "pyproject.toml" github-token: ${{ secrets.GITHUB_TOKEN }} - name: Install tox - run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv + run: uv tool install --python-preference only-managed --python 3.14 tox --with tox-uv - name: Install Python - if: startsWith(matrix.env, '3.') && matrix.env != '3.13' + if: startsWith(matrix.env, '3.') && matrix.env != '3.14' run: uv python install --python-preference only-managed ${{ matrix.env }} - name: Setup test suite run: tox run -vv --notest --skip-missing-interpreters false -e ${{ matrix.env }} diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a4c4f2f3..f773e029 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -20,7 +20,7 @@ jobs: cache-dependency-glob: "pyproject.toml" github-token: ${{ secrets.GITHUB_TOKEN }} - name: Build package - run: uv build --python 3.13 --python-preference only-managed --sdist --wheel . --out-dir dist + run: uv build --python 3.14 --python-preference only-managed --sdist --wheel . --out-dir dist - name: Store the distribution packages uses: actions/upload-artifact@v4 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1e2b6248..73f64b7c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,11 +20,11 @@ repos: - id: tox-ini-fmt args: ["-p", "fix"] - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.7.0" + rev: "v2.8.0" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.13.3" + rev: "v0.14.0" hooks: - id: ruff-format - id: ruff @@ -34,8 +34,8 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.5.1 - - "@prettier/plugin-xml@3.4.1" + - prettier@3.6.2 + - "@prettier/plugin-xml@3.4.2" - repo: meta hooks: - id: check-hooks-apply diff --git a/README.md b/README.md index 384e226f..db11c3d9 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,8 @@ The following configuration options are accepted: `True`, add stub documentation for undocumented parameters to be able to add type info. - `always_use_bars_union ` (default: `False`): If `True`, display Union's using the | operator described in PEP 604. (e.g `X` | `Y` or `int` | `None`). If `False`, Unions will display with the typing in brackets. (e.g. `Union[X, Y]` - or `Optional[int]`) + or `Optional[int]`). Note that on 3.14 and later this will always be `True` and not configurable due the interpreter + no longer differentiating between the two types, and we have no way to determine what the user used. - `typehints_document_rtype` (default: `True`): If `False`, never add an `:rtype:` directive. If `True`, add the `:rtype:` directive if no existing `:rtype:` is found. - `typehints_document_rtype_none` (default: `True`): If `False`, never add an `:rtype: None` directive. If `True`, add the `:rtype: None`. @@ -74,7 +75,6 @@ The following configuration options are accepted: [napoleon_use_rtype](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#confval-napoleon_use_rtype) to avoid generation of duplicate or redundant return type information. - `typehints_defaults` (default: `None`): If `None`, defaults are not added. Otherwise, adds a default annotation: - - `'comma'` adds it after the type, changing Sphinx’ default look to “**param** (_int_, default: `1`) -- text”. - `'braces'` adds `(default: ...)` after the type (useful for numpydoc like styles). - `'braces-after'` adds `(default: ...)` at the end of the parameter documentation text instead. diff --git a/pyproject.toml b/pyproject.toml index 37105b93..206a6cbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [build-system] build-backend = "hatchling.build" requires = [ - "hatch-vcs>=0.4", + "hatch-vcs>=0.5", "hatchling>=1.27", ] @@ -40,20 +40,20 @@ dynamic = [ "version", ] dependencies = [ - "sphinx>=8.2", + "sphinx>=8.2.3", ] optional-dependencies.docs = [ - "furo>=2024.8.6", + "furo>=2025.9.25", ] optional-dependencies.testing = [ "covdefaults>=2.3", - "coverage>=7.6.12", - "defusedxml>=0.7.1", # required by sphinx.testing - "diff-cover>=9.2.3", - "pytest>=8.3.4", - "pytest-cov>=6", - "sphobjinv>=2.3.1.2", - "typing-extensions>=4.12.2", + "coverage>=7.10.7", + "defusedxml>=0.7.1", # required by sphinx.testing + "diff-cover>=9.7.1", + "pytest>=8.4.2", + "pytest-cov>=7", + "sphobjinv>=2.3.1.3", + "typing-extensions>=4.15", ] urls.Changelog = "https://github.com/tox-dev/sphinx-autodoc-typehints/releases" urls.Homepage = "https://github.com/tox-dev/sphinx-autodoc-typehints" diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index c5475694..537add48 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -36,7 +36,17 @@ from sphinx.ext.autodoc import Options _LOGGER = logging.getLogger(__name__) -_PYDATA_ANNOTS_TYPING = {"Any", "AnyStr", "Callable", "ClassVar", "Literal", "NoReturn", "Optional", "Tuple", "Union"} +_PYDATA_ANNOTS_TYPING = { + "Any", + "AnyStr", + "Callable", + "ClassVar", + "Literal", + "NoReturn", + "Optional", + "Tuple", + *({"Union"} if sys.version_info < (3, 14) else set()), +} _PYDATA_ANNOTS_TYPES = { *("AsyncGeneratorType", "BuiltinFunctionType", "BuiltinMethodType"), *("CellType", "ClassMethodDescriptorType", "CoroutineType"), @@ -246,8 +256,10 @@ def format_annotation(annotation: Any, config: Config, *, short_literals: bool = formatted_args: str | None = "" always_use_bars_union: bool = getattr(config, "always_use_bars_union", True) - is_bars_union = full_name == "types.UnionType" or ( - always_use_bars_union and type(annotation).__qualname__ == "_UnionGenericAlias" + is_bars_union = ( + (sys.version_info >= (3, 14) and full_name == "typing.Union") + or full_name == "types.UnionType" + or (always_use_bars_union and type(annotation).__qualname__ == "_UnionGenericAlias") ) if is_bars_union: full_name = "" @@ -588,7 +600,7 @@ def _one_child(module: Module) -> stmt | None: return {} try: - type_comment = obj_ast.type_comment + type_comment = obj_ast.type_comment # type: ignore[attr-defined] except AttributeError: return {} @@ -610,7 +622,7 @@ def _one_child(module: Module) -> stmt | None: if comment_returns: rv["return"] = comment_returns - args = load_args(obj_ast) + args = load_args(obj_ast) # type: ignore[arg-type] comment_args = split_type_comment_args(comment_args_str) is_inline = len(comment_args) == 1 and comment_args[0] == "..." if not is_inline: diff --git a/tests/test_integration.py b/tests/test_integration.py index 02369f88..4bd3904c 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -92,7 +92,7 @@ class mod.Class(x, y, z=None) * **y** ("int") -- bar - * **z** ("Optional"["str"]) -- baz + * **z** ("str" | "None") -- baz class InnerClass @@ -117,7 +117,7 @@ class InnerClass * **y** ("int") -- bar - * **z** ("Optional"["str"]) -- baz + * **z** ("str" | "None") -- baz Return type: "str" @@ -131,7 +131,7 @@ class InnerClass * **y** ("int") -- bar - * **z** ("Optional"["str"]) -- baz + * **z** ("str" | "None") -- baz Return type: "str" @@ -149,7 +149,7 @@ class InnerClass * **y** ("int") -- bar - * **z** ("Optional"["str"]) -- baz + * **z** ("str" | "None") -- baz Return type: "str" @@ -284,7 +284,7 @@ def __init__(self, message: str) -> None: * **y** ("int") -- bar - * **z_** ("Optional"["str"]) -- baz + * **z_** ("str" | "None") -- baz Returns: something @@ -471,7 +471,7 @@ def method_without_typehint(self, x): # noqa: ANN001, ANN201, ARG002, PLR6301 Function docstring. Parameters: - * **x** ("Union"["str", "bytes", "None"]) -- foo + * **x** ("str" | "bytes" | "None") -- foo * **y** ("str") -- bar @@ -502,7 +502,7 @@ class mod.ClassWithTypehintsNotInline(x=None) Class docstring. Parameters: - **x** ("Optional"["Callable"[["int", "bytes"], "int"]]) -- foo + **x** ("Callable"[["int", "bytes"], "int"] | "None") -- foo foo(x=1) @@ -519,8 +519,7 @@ class mod.ClassWithTypehintsNotInline(x=None) Method docstring. Parameters: - **x** ("Optional"["Callable"[["int", "bytes"], "int"]]) -- - foo + **x** ("Callable"[["int", "bytes"], "int"] | "None") -- foo Return type: "ClassWithTypehintsNotInline" @@ -666,9 +665,9 @@ def func_with_overload(a: str, b: str) -> None: ... they must both have the same type. Parameters: - * **a** ("Union"["int", "str"]) -- The first thing + * **a** ("int" | "str") -- The first thing - * **b** ("Union"["int", "str"]) -- The second thing + * **b** ("int" | "str") -- The second thing Return type: "None" @@ -747,7 +746,7 @@ class mod.TestClassAttributeDocs A class - code: "Optional"["CodeType"] + code: "CodeType" | "None" An attribute """, @@ -1547,6 +1546,7 @@ def test_integration( (Path(app.srcdir) / "index.rst").write_text(template.format(val.__name__)) app.config.__dict__.update(configs[conf_run]) app.config.__dict__.update(val.OPTIONS) + app.config.always_use_bars_union = True monkeypatch.setitem(sys.modules, "mod", sys.modules[__name__]) app.build() assert "build succeeded" in status.getvalue() # Build succeeded diff --git a/tests/test_integration_autodoc_type_aliases.py b/tests/test_integration_autodoc_type_aliases.py index f9640420..5ee1fa4a 100644 --- a/tests/test_integration_autodoc_type_aliases.py +++ b/tests/test_integration_autodoc_type_aliases.py @@ -97,13 +97,13 @@ def g(s: AliasedClass) -> AliasedClass: @expected( - """\ + f"""\ mod.function(x, y) Function docstring. Parameters: - * **x** ("Optional"[Array]) -- foo + * **x** ({'Array | "None"' if sys.version_info >= (3, 14) else '"Optional"[Array]'}) -- foo * **y** ("Schema") -- boo diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index c0963c2c..097c0dc3 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -181,7 +181,7 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t pytest.param(Type[A], rf":py:class:`~typing.Type`\ \[:py:class:`~{__name__}.A`]", id="typing-A"), pytest.param(Any, ":py:data:`~typing.Any`", id="Any"), pytest.param(AnyStr, ":py:data:`~typing.AnyStr`", id="AnyStr"), - pytest.param(Generic[T], r":py:class:`~typing.Generic`\ \[:py:class:`~typing.TypeVar`\ \(``T``)]", id="Generic"), + pytest.param(Generic[T], r":py:class:`~typing.Generic`\ \[:py:class:`~typing.TypeVar`\ \(``T``)]", id="Generic"), # type: ignore[index] pytest.param(Mapping, ":py:class:`~collections.abc.Mapping`", id="Mapping"), pytest.param( Mapping[T, int], # type: ignore[valid-type] @@ -244,37 +244,63 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t r":py:data:`~typing.Tuple`\ \[:py:class:`str`, :py:data:`...`]", id="Tuple-str-Ellipsis", ), - pytest.param(Union, ":py:data:`~typing.Union`", id="Union"), + pytest.param(Union, "" if sys.version_info >= (3, 14) else ":py:data:`~typing.Union`", id="Union"), pytest.param( Union[str, bool], - r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`]", + ":py:class:`str` | :py:class:`bool`" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`]", id="Union-str-bool", ), pytest.param( Union[str, bool, None], - r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", + ":py:class:`str` | :py:class:`bool` | :py:obj:`None`" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", id="Union-str-bool-None", ), pytest.param( Union[str, Any], - r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:data:`~typing.Any`]", + ":py:class:`str` | :py:data:`~typing.Any`" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:data:`~typing.Any`]", id="Union-str-Any", ), pytest.param( Optional[str], - r":py:data:`~typing.Optional`\ \[:py:class:`str`]", + ":py:class:`str` | :py:obj:`None`" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Optional`\ \[:py:class:`str`]", id="Optional-str", ), pytest.param( Union[str, None], - r":py:data:`~typing.Optional`\ \[:py:class:`str`]", + ":py:class:`str` | :py:obj:`None`" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Optional`\ \[:py:class:`str`]", id="Optional-str-None", ), pytest.param( Optional[str | bool], - r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", + ":py:class:`str` | :py:class:`bool` | :py:obj:`None`" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Union`\ \[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", id="Optional-Union-str-bool", ), + pytest.param( + RecList, + ":py:class:`int` | :py:class:`~typing.List`\\ \\[RecList]" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Union`\ \[:py:class:`int`, :py:class:`~typing.List`\ \[RecList]]", + id="RecList", + ), + pytest.param( + MutualRecA, + ":py:class:`bool` | :py:class:`~typing.List`\\ \\[MutualRecB]" + if sys.version_info >= (3, 14) + else r":py:data:`~typing.Union`\ \[:py:class:`bool`, :py:class:`~typing.List`\ \[MutualRecB]]", + id="MutualRecA", + ), pytest.param(Callable, ":py:class:`~collections.abc.Callable`", id="Callable"), pytest.param( Callable[..., int], @@ -359,14 +385,6 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t r":py:data:`~typing.Tuple`\ \[:py:class:`int`, :py:data:`...`]", id="Tuple-p-Ellipsis", ), - pytest.param( - RecList, r":py:data:`~typing.Union`\ \[:py:class:`int`, :py:class:`~typing.List`\ \[RecList]]", id="RecList" - ), - pytest.param( - MutualRecA, - r":py:data:`~typing.Union`\ \[:py:class:`bool`, :py:class:`~typing.List`\ \[MutualRecB]]", - id="MutualRecA", - ), ] @@ -418,7 +436,9 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str assert format_annotation(annotation, conf) == expected_result # Test for the correct role (class vs data) using the official Sphinx inventory - if any(modname in expected_result for modname in ("typing", "types")): + if any(modname in expected_result for modname in ("typing", "types")) and not ( + sys.version_info >= (3, 14) and isinstance(annotation, Union) + ): m = re.match(r"^:py:(?Pclass|data|func):`~(?P[^`]+)`", result) assert m, "No match" name = m.group("name") diff --git a/tox.ini b/tox.ini index 87924c5a..e7e0a31b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,15 @@ [tox] requires = - tox>=4.24.1 - tox-uv>=1.24 + tox>=4.30.2 + tox-uv>=1.28 env_list = fix + 3.14 3.13 3.12 3.11 type + 3.14t pkg_meta skip_missing_interpreters = true @@ -37,15 +39,15 @@ commands = description = format the code base to adhere to our styles, and complain about what we cannot do automatically skip_install = true deps = - pre-commit-uv>=4.1.4 + pre-commit-uv>=4.1.5 commands = pre-commit run --all-files --show-diff-on-failure [testenv:type] description = run type check on code base deps = - mypy==1.15 - types-docutils>=0.21.0.20250604 + mypy==1.18.2 + types-docutils>=0.22.2.20250924 commands = mypy src mypy tests @@ -54,9 +56,9 @@ commands = description = check that the long description is valid skip_install = true deps = - check-wheel-contents>=0.6.1 - twine>=6.1 - uv>=0.6.1 + check-wheel-contents>=0.6.3 + twine>=6.2 + uv>=0.8.22 commands = uv build --sdist --wheel --out-dir {env_tmp_dir} . twine check {env_tmp_dir}{/}* From 92e975155440d5d473ea27c9eb048fef43f3dab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Thu, 9 Oct 2025 11:14:07 -0700 Subject: [PATCH 55/56] Support Union type on its own (#570) --- .pre-commit-config.yaml | 2 +- src/sphinx_autodoc_typehints/__init__.py | 2 ++ tests/test_sphinx_autodoc_typehints.py | 29 +++++++++++++++--------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 73f64b7c..705e2e6b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,7 +27,7 @@ repos: rev: "v0.14.0" hooks: - id: ruff-format - - id: ruff + - id: ruff-check args: ["--fix", "--unsafe-fixes", "--exit-non-zero-on-fix"] - repo: https://github.com/rbubley/mirrors-prettier rev: "v3.6.2" # Use the sha / tag you want to point at diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index 537add48..1c1a3c2d 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -300,6 +300,8 @@ def format_annotation(annotation: Any, config: Config, *, short_literals: bool = return f"\\{' | '.join(f'``{arg!r}``' for arg in args)}" formatted_args = f"\\[{', '.join(f'``{arg!r}``' for arg in args)}]" elif is_bars_union: + if not args: + return f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`{prefix}typing.Union`" return " | ".join([format_annotation(arg, config, short_literals=short_literals) for arg in args]) if args and not formatted_args: diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index 097c0dc3..ea537113 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -244,7 +244,10 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t r":py:data:`~typing.Tuple`\ \[:py:class:`str`, :py:data:`...`]", id="Tuple-str-Ellipsis", ), - pytest.param(Union, "" if sys.version_info >= (3, 14) else ":py:data:`~typing.Union`", id="Union"), + pytest.param(Union, f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`~typing.Union`", id="Union"), + pytest.param( + types.UnionType, f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`~typing.Union`", id="UnionType" + ), pytest.param( Union[str, bool], ":py:class:`str` | :py:class:`bool`" @@ -280,6 +283,12 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t else r":py:data:`~typing.Optional`\ \[:py:class:`str`]", id="Optional-str-None", ), + pytest.param( + type[T] | types.UnionType, + ":py:class:`type`\\ \\[:py:class:`~typing.TypeVar`\\ \\(``T``)] | " + f":py:{'class' if sys.version_info >= (3, 14) else 'data'}:`~typing.Union`", + id="typevar union bar uniontype", + ), pytest.param( Optional[str | bool], ":py:class:`str` | :py:class:`bool` | :py:obj:`None`" @@ -436,18 +445,16 @@ def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str assert format_annotation(annotation, conf) == expected_result # Test for the correct role (class vs data) using the official Sphinx inventory - if any(modname in expected_result for modname in ("typing", "types")) and not ( - sys.version_info >= (3, 14) and isinstance(annotation, Union) + if ( + result.count(":py:") == 1 + and ("typing" in result or "types" in result) + and (match := re.match(r"^:py:(?Pclass|data|func):`~(?P[^`]+)`", result)) ): - m = re.match(r"^:py:(?Pclass|data|func):`~(?P[^`]+)`", result) - assert m, "No match" - name = m.group("name") + name = match.group("name") expected_role = next((o.role for o in inv.objects if o.name == name), None) - if expected_role: - if expected_role == "function": - expected_role = "func" - - assert m.group("role") == expected_role + if expected_role and expected_role == "function": + expected_role = "func" + assert match.group("role") == expected_role @pytest.mark.parametrize( From 41100f97b15bf3e6016803805f9befb2937a3ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Thu, 9 Oct 2025 11:21:20 -0700 Subject: [PATCH 56/56] Declare 3.14 support (#571) --- .github/release.yml | 4 ++-- .pre-commit-config.yaml | 2 +- pyproject.toml | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/release.yml b/.github/release.yml index 9d1e0987..5f89818f 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -1,5 +1,5 @@ changelog: exclude: authors: - - dependabot - - pre-commit-ci + - dependabot[bot] + - pre-commit-ci[bot] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 705e2e6b..62da4c0f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -20,7 +20,7 @@ repos: - id: tox-ini-fmt args: ["-p", "fix"] - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.8.0" + rev: "v2.10.0" hooks: - id: pyproject-fmt - repo: https://github.com/astral-sh/ruff-pre-commit diff --git a/pyproject.toml b/pyproject.toml index 206a6cbe..47b54378 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Documentation :: Sphinx", ] dynamic = [ @@ -111,7 +112,7 @@ write-changes = true count = true [tool.pyproject-fmt] -max_supported_python = "3.13" +max_supported_python = "3.14" [tool.pytest.ini_options] testpaths = [