From 483a4b3492cdebc6a29f11c59ed54fdfeeed21cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bern=C3=A1t=20G=C3=A1bor?= Date: Thu, 15 Jun 2023 13:47:59 -0700 Subject: [PATCH] Test against 3.12 beta 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Bernát Gábor --- .github/workflows/check.yml | 8 +- .github/workflows/release.yml | 2 +- pyproject.toml | 6 +- src/sphinx_autodoc_typehints/__init__.py | 2 +- tests/test_sphinx_autodoc_typehints.py | 332 ++++++++++++----------- tox.ini | 7 +- 6 files changed, 185 insertions(+), 172 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index c0881035..e7a53b40 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -13,12 +13,12 @@ concurrency: jobs: test: name: test with CPython ${{ matrix.py }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: py: - - "3.12.0-alpha.7" + - "3.12.0-beta.2" - "3.11" - "3.10" - "3.9" @@ -68,7 +68,7 @@ jobs: coverage: name: Combine coverage - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest needs: test steps: - uses: actions/checkout@v3 @@ -100,7 +100,7 @@ jobs: check: name: tox env ${{ matrix.tox_env }} - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9099a523..2644500c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,7 +5,7 @@ on: jobs: release: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest environment: name: release url: https://pypi.org/p/sphinx-autodoc-typehints diff --git a/pyproject.toml b/pyproject.toml index 62a96ce2..d5a85922 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,11 +45,13 @@ optional-dependencies.docs = [ "sphinx>=7.0.1", "sphinx-autodoc-typehints>=1.23.4", ] +optional-dependencies.numpy = [ + "nptyping>=2.5", +] optional-dependencies.testing = [ "covdefaults>=2.3", "coverage>=7.2.7", "diff-cover>=7.5", - "nptyping>=2.5", "pytest>=7.3.1", "pytest-cov>=4.1", "sphobjinv>=2.3.1", @@ -84,7 +86,7 @@ paths.source = [ "*/src", "*\\src", ] -report.fail_under = 81 +report.fail_under = 85 report.omit = [] run.parallel = true run.plugins = ["covdefaults"] diff --git a/src/sphinx_autodoc_typehints/__init__.py b/src/sphinx_autodoc_typehints/__init__.py index f6e1beaf..c59610ab 100644 --- a/src/sphinx_autodoc_typehints/__init__.py +++ b/src/sphinx_autodoc_typehints/__init__.py @@ -244,7 +244,7 @@ def format_annotation(annotation: Any, config: Config) -> str: # noqa: C901, PL fmt = [format_annotation(arg, config) for arg in args] formatted_args = f"\\[\\[{', '.join(fmt[:-1])}], {fmt[-1]}]" elif full_name == "typing.Literal": - formatted_args = "\\[{}]".format(", ".join(f"``{arg!r}``" for arg in args)) + formatted_args = f"\\[{', '.join(f'``{arg!r}``' for arg in args)}]" elif full_name == "types.UnionType": return " | ".join([format_annotation(arg, config) for arg in args]) diff --git a/tests/test_sphinx_autodoc_typehints.py b/tests/test_sphinx_autodoc_typehints.py index f964f6e6..5ff472d5 100644 --- a/tests/test_sphinx_autodoc_typehints.py +++ b/tests/test_sphinx_autodoc_typehints.py @@ -30,7 +30,6 @@ ) from unittest.mock import create_autospec, patch -import nptyping import pytest import typing_extensions from sphinx.application import Sphinx @@ -50,6 +49,11 @@ from sphinx.testing.util import SphinxTestApp from sphobjinv import Inventory +try: + import nptyping +except ImportError: + nptyping = None # type: ignore[assignment] + T = TypeVar("T") U = TypeVar("U", covariant=True) V = TypeVar("V", contravariant=True) @@ -114,6 +118,7 @@ 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): AbcCallable = collections.abc.Callable # type: ignore[type-arg] @@ -186,177 +191,182 @@ def test_parse_annotation(annotation: Any, module: str, class_name: str, args: t assert (got_mod, got_cls, got_args) == (module, class_name, args) -@pytest.mark.parametrize( - ("annotation", "expected_result"), - [ - (str, ":py:class:`str`"), - (int, ":py:class:`int`"), - (StringIO, ":py:class:`~io.StringIO`"), - (FunctionType, ":py:class:`~types.FunctionType`"), - (ModuleType, ":py:class:`~types.ModuleType`"), - (type(None), ":py:obj:`None`"), - (type, ":py:class:`type`"), - (collections.abc.Callable, ":py:class:`~collections.abc.Callable`"), - (Type, ":py:class:`~typing.Type`"), - (Type[A], ":py:class:`~typing.Type`\\[:py:class:`~%s.A`]" % __name__), - (Any, ":py:data:`~typing.Any`"), - (AnyStr, ":py:data:`~typing.AnyStr`"), - (Generic[T], ":py:class:`~typing.Generic`\\[:py:class:`~typing.TypeVar`\\(``T``)]"), - (Mapping, ":py:class:`~typing.Mapping`"), - ( - Mapping[T, int], # type: ignore[valid-type] - ":py:class:`~typing.Mapping`\\[:py:class:`~typing.TypeVar`\\(``T``), :py:class:`int`]", - ), - ( - Mapping[str, V], # type: ignore[valid-type] - ":py:class:`~typing.Mapping`\\[:py:class:`str`, :py:class:`~typing.TypeVar`\\(``V``, contravariant=True)]", - ), - ( - Mapping[T, U], # type: ignore[valid-type] - ":py:class:`~typing.Mapping`\\[:py:class:`~typing.TypeVar`\\(``T``), " - ":py:class:`~typing.TypeVar`\\(``U``, covariant=True)]", - ), - (Mapping[str, bool], ":py:class:`~typing.Mapping`\\[:py:class:`str`, :py:class:`bool`]"), - (Dict, ":py:class:`~typing.Dict`"), - ( - Dict[T, int], # type: ignore[valid-type] - ":py:class:`~typing.Dict`\\[:py:class:`~typing.TypeVar`\\(``T``), :py:class:`int`]", - ), - ( - Dict[str, V], # type: ignore[valid-type] - ":py:class:`~typing.Dict`\\[:py:class:`str`, :py:class:`~typing.TypeVar`\\(``V``, contravariant=True)]", - ), - ( - Dict[T, U], # type: ignore[valid-type] - ":py:class:`~typing.Dict`\\[:py:class:`~typing.TypeVar`\\(``T``)," - " :py:class:`~typing.TypeVar`\\(``U``, covariant=True)]", - ), - (Dict[str, bool], ":py:class:`~typing.Dict`\\[:py:class:`str`, :py:class:`bool`]"), - (Tuple, ":py:data:`~typing.Tuple`"), - (Tuple[str, bool], ":py:data:`~typing.Tuple`\\[:py:class:`str`, :py:class:`bool`]"), - (Tuple[int, int, int], ":py:data:`~typing.Tuple`\\[:py:class:`int`, :py:class:`int`, :py:class:`int`]"), - (Tuple[str, ...], ":py:data:`~typing.Tuple`\\[:py:class:`str`, :py:data:`...`]"), - (Union, ":py:data:`~typing.Union`"), - (Union[str, bool], ":py:data:`~typing.Union`\\[:py:class:`str`, :py:class:`bool`]"), - (Union[str, bool, None], ":py:data:`~typing.Union`\\[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]"), - pytest.param( - Union[str, Any], - ":py:data:`~typing.Union`\\[:py:class:`str`, :py:data:`~typing.Any`]", - marks=pytest.mark.skipif( - (3, 5, 0) <= sys.version_info[:3] <= (3, 5, 2), - reason="Union erases the str on 3.5.0 -> 3.5.2", +_CASES = [ + (str, ":py:class:`str`"), + (int, ":py:class:`int`"), + (StringIO, ":py:class:`~io.StringIO`"), + (FunctionType, ":py:class:`~types.FunctionType`"), + (ModuleType, ":py:class:`~types.ModuleType`"), + (type(None), ":py:obj:`None`"), + (type, ":py:class:`type`"), + (collections.abc.Callable, ":py:class:`~collections.abc.Callable`"), + (Type, ":py:class:`~typing.Type`"), + (Type[A], ":py:class:`~typing.Type`\\[:py:class:`~%s.A`]" % __name__), + (Any, ":py:data:`~typing.Any`"), + (AnyStr, ":py:data:`~typing.AnyStr`"), + (Generic[T], ":py:class:`~typing.Generic`\\[:py:class:`~typing.TypeVar`\\(``T``)]"), + (Mapping, ":py:class:`~typing.Mapping`"), + ( + Mapping[T, int], # type: ignore[valid-type] + ":py:class:`~typing.Mapping`\\[:py:class:`~typing.TypeVar`\\(``T``), :py:class:`int`]", + ), + ( + Mapping[str, V], # type: ignore[valid-type] + ":py:class:`~typing.Mapping`\\[:py:class:`str`, :py:class:`~typing.TypeVar`\\(``V``, contravariant=True)]", + ), + ( + Mapping[T, U], # type: ignore[valid-type] + ":py:class:`~typing.Mapping`\\[:py:class:`~typing.TypeVar`\\(``T``), " + ":py:class:`~typing.TypeVar`\\(``U``, covariant=True)]", + ), + (Mapping[str, bool], ":py:class:`~typing.Mapping`\\[:py:class:`str`, :py:class:`bool`]"), + (Dict, ":py:class:`~typing.Dict`"), + ( + Dict[T, int], # type: ignore[valid-type] + ":py:class:`~typing.Dict`\\[:py:class:`~typing.TypeVar`\\(``T``), :py:class:`int`]", + ), + ( + Dict[str, V], # type: ignore[valid-type] + ":py:class:`~typing.Dict`\\[:py:class:`str`, :py:class:`~typing.TypeVar`\\(``V``, contravariant=True)]", + ), + ( + Dict[T, U], # type: ignore[valid-type] + ":py:class:`~typing.Dict`\\[:py:class:`~typing.TypeVar`\\(``T``)," + " :py:class:`~typing.TypeVar`\\(``U``, covariant=True)]", + ), + (Dict[str, bool], ":py:class:`~typing.Dict`\\[:py:class:`str`, :py:class:`bool`]"), + (Tuple, ":py:data:`~typing.Tuple`"), + (Tuple[str, bool], ":py:data:`~typing.Tuple`\\[:py:class:`str`, :py:class:`bool`]"), + (Tuple[int, int, int], ":py:data:`~typing.Tuple`\\[:py:class:`int`, :py:class:`int`, :py:class:`int`]"), + (Tuple[str, ...], ":py:data:`~typing.Tuple`\\[:py:class:`str`, :py:data:`...`]"), + (Union, ":py:data:`~typing.Union`"), + (Union[str, bool], ":py:data:`~typing.Union`\\[:py:class:`str`, :py:class:`bool`]"), + (Union[str, bool, None], ":py:data:`~typing.Union`\\[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]"), + pytest.param(Union[str, Any], ":py:data:`~typing.Union`\\[:py:class:`str`, :py:data:`~typing.Any`]"), + (Optional[str], ":py:data:`~typing.Optional`\\[:py:class:`str`]"), + (Union[str, None], ":py:data:`~typing.Optional`\\[:py:class:`str`]"), + ( + Optional[Union[str, bool]], + ":py:data:`~typing.Union`\\[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", + ), + (Callable, ":py:data:`~typing.Callable`"), + (Callable[..., int], ":py:data:`~typing.Callable`\\[:py:data:`...`, :py:class:`int`]"), + (Callable[[int], int], ":py:data:`~typing.Callable`\\[\\[:py:class:`int`], :py:class:`int`]"), + ( + Callable[[int, str], bool], + ":py:data:`~typing.Callable`\\[\\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", + ), + ( + Callable[[int, str], None], + ":py:data:`~typing.Callable`\\[\\[:py:class:`int`, :py:class:`str`], :py:obj:`None`]", + ), + ( + Callable[[T], T], + ":py:data:`~typing.Callable`\\[\\[:py:class:`~typing.TypeVar`\\(``T``)]," + " :py:class:`~typing.TypeVar`\\(``T``)]", + ), + ( + AbcCallable[[int, str], bool], # type: ignore[valid-type,misc,type-arg] + ":py:class:`~collections.abc.Callable`\\[\\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", + ), + (Pattern, ":py:class:`~typing.Pattern`"), + (Pattern[str], ":py:class:`~typing.Pattern`\\[:py:class:`str`]"), + (IO, ":py:class:`~typing.IO`"), + (IO[str], ":py:class:`~typing.IO`\\[:py:class:`str`]"), + (Metaclass, ":py:class:`~%s.Metaclass`" % __name__), + (A, ":py:class:`~%s.A`" % __name__), + (B, ":py:class:`~%s.B`" % __name__), + (B[int], ":py:class:`~%s.B`\\[:py:class:`int`]" % __name__), + (C, ":py:class:`~%s.C`" % __name__), + (D, ":py:class:`~%s.D`" % __name__), + (E, ":py:class:`~%s.E`" % __name__), + (E[int], ":py:class:`~%s.E`\\[:py:class:`int`]" % __name__), + (W, f":py:{'class' if PY310_PLUS else 'func'}:`~typing.NewType`\\(``W``, :py:class:`str`)"), + (T, ":py:class:`~typing.TypeVar`\\(``T``)"), + (U, ":py:class:`~typing.TypeVar`\\(``U``, covariant=True)"), + (V, ":py:class:`~typing.TypeVar`\\(``V``, contravariant=True)"), + (X, ":py:class:`~typing.TypeVar`\\(``X``, :py:class:`str`, :py:class:`int`)"), + (Y, ":py:class:`~typing.TypeVar`\\(``Y``, bound= :py:class:`str`)"), + (Z, ":py:class:`~typing.TypeVar`\\(``Z``, bound= A)"), + (S, ":py:class:`~typing.TypeVar`\\(``S``, bound= miss)"), + # ParamSpec should behave like TypeVar, except for missing constraints + (P, f":py:class:`~typing.ParamSpec`\\(``P``{', bound= :py:obj:`None`' if PY312_PLUS else ''})"), + ( + P_co, + f":py:class:`~typing.ParamSpec`\\(``P_co``{', bound= :py:obj:`None`' if PY312_PLUS else ''}, covariant=True)", + ), + ( + P_contra, + f":py:class:`~typing.ParamSpec`\\(``P_contra``{', bound= :py:obj:`None`' if PY312_PLUS else ''}" + ", contravariant=True)", + ), + (P_bound, ":py:class:`~typing.ParamSpec`\\(``P_bound``, bound= :py:class:`str`)"), + # ## These test for correct internal tuple rendering, even if not all are valid Tuple types + # Zero-length tuple remains + (Tuple[()], ":py:data:`~typing.Tuple`"), + # Internal single tuple with simple types is flattened in the output + (Tuple[(int,)], ":py:data:`~typing.Tuple`\\[:py:class:`int`]"), + (Tuple[(int, int)], ":py:data:`~typing.Tuple`\\[:py:class:`int`, :py:class:`int`]"), + # Ellipsis in single tuple also gets flattened + (Tuple[(int, ...)], ":py:data:`~typing.Tuple`\\[:py:class:`int`, :py:data:`...`]"), + ( + RecList, + ":py:data:`~typing.Union`\\[:py:class:`int`, :py:class:`~typing.List`\\[RecList]]", + ), + ( + MutualRecA, + ":py:data:`~typing.Union`\\[:py:class:`bool`, :py:class:`~typing.List`\\[MutualRecB]]", + ), +] + +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 + ( + nptyping.NDArray[nptyping.Shape["*"], nptyping.Float], + ( + ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[*], " + ":py:class:`~numpy.float64`]" + ), ), - ), - (Optional[str], ":py:data:`~typing.Optional`\\[:py:class:`str`]"), - (Union[str, None], ":py:data:`~typing.Optional`\\[:py:class:`str`]"), - ( - Optional[Union[str, bool]], - ":py:data:`~typing.Union`\\[:py:class:`str`, :py:class:`bool`, :py:obj:`None`]", - ), - (Callable, ":py:data:`~typing.Callable`"), - (Callable[..., int], ":py:data:`~typing.Callable`\\[:py:data:`...`, :py:class:`int`]"), - (Callable[[int], int], ":py:data:`~typing.Callable`\\[\\[:py:class:`int`], :py:class:`int`]"), - ( - Callable[[int, str], bool], - ":py:data:`~typing.Callable`\\[\\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", - ), - ( - Callable[[int, str], None], - ":py:data:`~typing.Callable`\\[\\[:py:class:`int`, :py:class:`str`], :py:obj:`None`]", - ), - ( - Callable[[T], T], - ":py:data:`~typing.Callable`\\[\\[:py:class:`~typing.TypeVar`\\(``T``)]," - " :py:class:`~typing.TypeVar`\\(``T``)]", - ), - ( - AbcCallable[[int, str], bool], # type: ignore[valid-type,misc,type-arg] - ":py:class:`~collections.abc.Callable`\\[\\[:py:class:`int`, :py:class:`str`], :py:class:`bool`]", - ), - (Pattern, ":py:class:`~typing.Pattern`"), - (Pattern[str], ":py:class:`~typing.Pattern`\\[:py:class:`str`]"), - (IO, ":py:class:`~typing.IO`"), - (IO[str], ":py:class:`~typing.IO`\\[:py:class:`str`]"), - (Metaclass, ":py:class:`~%s.Metaclass`" % __name__), - (A, ":py:class:`~%s.A`" % __name__), - (B, ":py:class:`~%s.B`" % __name__), - (B[int], ":py:class:`~%s.B`\\[:py:class:`int`]" % __name__), - (C, ":py:class:`~%s.C`" % __name__), - (D, ":py:class:`~%s.D`" % __name__), - (E, ":py:class:`~%s.E`" % __name__), - (E[int], ":py:class:`~%s.E`\\[:py:class:`int`]" % __name__), - (W, f':py:{"class" if PY310_PLUS else "func"}:' f"`~typing.NewType`\\(``W``, :py:class:`str`)"), # noqa: ISC001 - (T, ":py:class:`~typing.TypeVar`\\(``T``)"), - (U, ":py:class:`~typing.TypeVar`\\(``U``, covariant=True)"), - (V, ":py:class:`~typing.TypeVar`\\(``V``, contravariant=True)"), - (X, ":py:class:`~typing.TypeVar`\\(``X``, :py:class:`str`, :py:class:`int`)"), - (Y, ":py:class:`~typing.TypeVar`\\(``Y``, bound= :py:class:`str`)"), - (Z, ":py:class:`~typing.TypeVar`\\(``Z``, bound= A)"), - (S, ":py:class:`~typing.TypeVar`\\(``S``, bound= miss)"), - # ParamSpec should behave like TypeVar, except for missing constraints - (P, ":py:class:`~typing.ParamSpec`\\(``P``)"), - (P_co, ":py:class:`~typing.ParamSpec`\\(``P_co``, covariant=True)"), - (P_contra, ":py:class:`~typing.ParamSpec`\\(``P_contra``, contravariant=True)"), - (P_bound, ":py:class:`~typing.ParamSpec`\\(``P_bound``, bound= :py:class:`str`)"), - # ## These test for correct internal tuple rendering, even if not all are valid Tuple types - # Zero-length tuple remains - (Tuple[()], ":py:data:`~typing.Tuple`"), - # Internal single tuple with simple types is flattened in the output - (Tuple[(int,)], ":py:data:`~typing.Tuple`\\[:py:class:`int`]"), - (Tuple[(int, int)], ":py:data:`~typing.Tuple`\\[:py:class:`int`, :py:class:`int`]"), - # Ellipsis in single tuple also gets flattened - (Tuple[(int, ...)], ":py:data:`~typing.Tuple`\\[:py:class:`int`, :py:data:`...`]"), - # Internal tuple with following additional type cannot be flattened (specific to nptyping?) - # These cases will fail if nptyping restructures its internal module hierarchy - ( - nptyping.NDArray[nptyping.Shape["*"], nptyping.Float], ( - ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[*], " - ":py:class:`~numpy.float64`]" + nptyping.NDArray[nptyping.Shape["64"], nptyping.Float], + ( + ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[64]," + " :py:class:`~numpy.float64`]" + ), ), - ), - ( - nptyping.NDArray[nptyping.Shape["64"], nptyping.Float], ( - ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[64]," - " :py:class:`~numpy.float64`]" + nptyping.NDArray[nptyping.Shape["*, *"], nptyping.Float], + ( + ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[*, " + "*], :py:class:`~numpy.float64`]" + ), ), - ), - ( - nptyping.NDArray[nptyping.Shape["*, *"], nptyping.Float], ( - ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[*, " - "*], :py:class:`~numpy.float64`]" + nptyping.NDArray[nptyping.Shape["*, ..."], nptyping.Float], + ":py:class:`~nptyping.ndarray.NDArray`\\[:py:data:`~typing.Any`, :py:class:`~numpy.float64`]", ), - ), - ( - nptyping.NDArray[nptyping.Shape["*, ..."], nptyping.Float], - ":py:class:`~nptyping.ndarray.NDArray`\\[:py:data:`~typing.Any`, :py:class:`~numpy.float64`]", - ), - ( - nptyping.NDArray[nptyping.Shape["*, 3"], nptyping.Float], ( - ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[*, 3" - "], :py:class:`~numpy.float64`]" + nptyping.NDArray[nptyping.Shape["*, 3"], nptyping.Float], + ( + ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[*, 3" + "], :py:class:`~numpy.float64`]" + ), ), - ), - ( - nptyping.NDArray[nptyping.Shape["3, ..."], nptyping.Float], ( - ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[3, " - "...], :py:class:`~numpy.float64`]" + nptyping.NDArray[nptyping.Shape["3, ..."], nptyping.Float], + ( + ":py:class:`~nptyping.ndarray.NDArray`\\[:py:class:`~nptyping.base_meta_classes.Shape`\\[3, " + "...], :py:class:`~numpy.float64`]" + ), ), - ), - ( - RecList, - ":py:data:`~typing.Union`\\[:py:class:`int`, :py:class:`~typing.List`\\[RecList]]", - ), - ( - MutualRecA, - ":py:data:`~typing.Union`\\[:py:class:`bool`, :py:class:`~typing.List`\\[MutualRecB]]", - ), - ], -) + ], + ) + + +@pytest.mark.parametrize(("annotation", "expected_result"), _CASES) def test_format_annotation(inv: Inventory, annotation: Any, expected_result: str) -> None: conf = create_autospec(Config, _annotation_globals=globals()) result = format_annotation(annotation, conf) diff --git a/tox.ini b/tox.ini index 77358498..90bb23cb 100644 --- a/tox.ini +++ b/tox.ini @@ -19,6 +19,7 @@ description = run tests with {basepython} package = wheel wheel_build_env = .pkg extras = + numpy testing type-comment pass_env = @@ -43,9 +44,9 @@ commands = pre-commit run --all-files --show-diff-on-failure [testenv:py312] -set_env = - {[testenv]set_env} - VIRTUALENV_SETUPTOOLS = bundle +extras = + testing + type-comment [testenv:type] description = run type check on code base