From 07bec79d4c5becaaac142a60f462fb86a204b831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Thu, 2 Jan 2025 16:11:39 -0800 Subject: [PATCH] Drop support for nptyping 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