Skip to content

Commit 14a43c0

Browse files
authored
feat: add support for TypeAliasType (#237)
1 parent c2a309d commit 14a43c0

File tree

15 files changed

+142
-71
lines changed

15 files changed

+142
-71
lines changed

.github/workflows/ci.yml

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,67 @@ env:
1818
FORCE_COLOR: "1"
1919

2020
jobs:
21-
build:
21+
get-environments:
22+
runs-on: ubuntu-latest
23+
outputs:
24+
envs: ${{ steps.get-envs.outputs.envs }}
25+
steps:
26+
- uses: actions/checkout@v5
27+
with: { filter: "blob:none", fetch-depth: 0 }
28+
- uses: astral-sh/setup-uv@v7
29+
with: { enable-cache: false }
30+
- id: get-envs
31+
run: |
32+
ENVS_JSON=$(NO_COLOR=1 uvx hatch env show --json | jq -c 'to_entries
33+
| map(
34+
select(.key | startswith("hatch-test"))
35+
| { name: .key, python: .value.python }
36+
)')
37+
echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT
38+
39+
test:
40+
needs: get-environments
2241
runs-on: ubuntu-latest
2342
strategy:
2443
matrix:
25-
python-version: ["3.10", "3.11", "3.12"]
44+
env: ${{ fromJSON(needs.get-environments.outputs.envs) }}
2645
steps:
27-
- uses: actions/checkout@v4
46+
- uses: actions/checkout@v5
47+
with: { fetch-depth: 0, filter: "blob:none" }
48+
- uses: astral-sh/setup-uv@v7
2849
with:
29-
fetch-depth: 0
30-
filter: blob:none
31-
- uses: actions/setup-python@v5
32-
with:
33-
python-version: ${{ matrix.python-version }}
34-
- uses: hynek/setup-cached-uv@v2
35-
with:
36-
cache-dependency-path: pyproject.toml
37-
- name: dependencies
38-
# TODO: remove typer constraint after fixing https://github.com/WaylonWalker/coverage-rich/issues/4
39-
run: uv pip install --system .[test,typehints,myst] coverage-rich 'typer <0.14' 'anyconfig[toml] >=0.14'
40-
- name: tests
41-
run: coverage run -m pytest --verbose --color=yes
42-
- name: show coverage
43-
run: coverage-rich report
50+
python-version: ${{ matrix.env.python-version }}
51+
- name: Install dependencies
52+
run: |
53+
uv tool install hatch
54+
hatch -v env create ${{ matrix.env.name }}
55+
- name: Run tests
56+
run: |
57+
hatch run ${{ matrix.env.name }}:run-cov -v --color=yes -n auto --junitxml=test-data/test-results.xml
58+
hatch run ${{ matrix.env.name }}:cov-combine
59+
hatch run ${{ matrix.env.name }}:coverage xml
4460
- name: upload coverage
61+
if: ${{ !cancelled() }}
4562
uses: codecov/codecov-action@v5
4663
with:
64+
token: c66a2830-d3c7-4ae7-a230-21aef89dcf65
65+
flags: ${{ matrix.env.name }}
4766
fail_ci_if_error: true
67+
- name: Upload test results
68+
if: ${{ !cancelled() }}
69+
uses: codecov/test-results-action@v1
70+
with:
4871
token: c66a2830-d3c7-4ae7-a230-21aef89dcf65
72+
flags: ${{ matrix.env.name }}
73+
fail_ci_if_error: true
74+
75+
check:
76+
if: always()
77+
needs:
78+
- get-environments
79+
- test
80+
runs-on: ubuntu-latest
81+
steps:
82+
- uses: re-actors/alls-green@release/v1
83+
with:
84+
jobs: ${{ toJSON(needs) }}

.pre-commit-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ repos:
2626
- types-docutils
2727
- legacy-api-wrap
2828
- myst-parser
29+
- sphinx-autodoc-typehints

docs/conf.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
import re
66
from typing import TYPE_CHECKING
77
from pathlib import PurePosixPath
8-
from datetime import datetime
9-
from datetime import timezone as tz
8+
from datetime import UTC, datetime
109
from importlib.metadata import metadata
1110

1211
from jinja2.tests import TESTS
@@ -42,7 +41,7 @@
4241
meta = metadata("scanpydoc")
4342
project = meta["name"]
4443
author = meta["author-email"].split(" <")[0]
45-
copyright = f"{datetime.now(tz=tz.utc):%Y}, {author}." # noqa: A001
44+
copyright = f"{datetime.now(tz=UTC):%Y}, {author}." # noqa: A001
4645
version = release = meta["version"]
4746

4847
master_doc = "index"

pyproject.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ classifiers = [
1717
'Framework :: Sphinx :: Extension',
1818
'Typing :: Typed',
1919
]
20-
requires-python = '>=3.10'
20+
requires-python = '>=3.12'
2121
dependencies = [
2222
'sphinx>=7.0',
2323
]
@@ -94,14 +94,16 @@ version-file = 'src/scanpydoc/_version.py'
9494
[tool.hatch.envs.default]
9595
dependencies = ['types-docutils']
9696
[tool.hatch.envs.docs]
97-
python = '3.11'
97+
python = '3.13'
9898
features = ['doc']
9999
[tool.hatch.envs.docs.scripts]
100100
build = 'sphinx-build -M html docs docs/_build'
101101
clean = 'git clean -fdX docs'
102102

103103
[tool.hatch.envs.hatch-test]
104104
features = ['test', 'typehints', 'myst']
105+
[[tool.hatch.envs.hatch-test.matrix]]
106+
python = ['3.12', '3.14']
105107

106108
[tool.pytest.ini_options]
107109
addopts = [
@@ -115,8 +117,10 @@ filterwarnings = [
115117

116118
[tool.coverage.run]
117119
source_pkgs = ['scanpydoc']
120+
concurrency = ['multiprocessing']
121+
patch = ['subprocess']
118122
[tool.coverage.paths]
119-
scanpydoc = ['src/scanpydoc']
123+
source = ['src']
120124
[tool.coverage.report]
121125
exclude_lines = [
122126
'no cov',

src/scanpydoc/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from __future__ import annotations
77

8-
from typing import TYPE_CHECKING, Any, TypeVar
8+
from typing import TYPE_CHECKING, Any
99
from textwrap import indent
1010
from collections.abc import Callable
1111

@@ -31,10 +31,8 @@
3131
:ref:`Metadata <sphinx:ext-metadata>` for this extension.
3232
"""
3333

34-
C = TypeVar("C", bound=Callable[..., Any])
3534

36-
37-
def _setup_sig(fn: C) -> C:
35+
def _setup_sig[C: Callable[..., Any]](fn: C) -> C:
3836
fn.__doc__ = f"{fn.__doc__ or ''}\n\n{indent(setup_sig_str, ' ' * 4)}"
3937
return fn
4038

src/scanpydoc/autosummary_generate_imported.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,7 @@
1313

1414

1515
if TYPE_CHECKING:
16-
import sys
17-
18-
if sys.version_info >= (3, 11):
19-
from typing import Never
20-
else: # pragma: no cover
21-
from typing import NoReturn as Never
16+
from typing import Never
2217

2318
from sphinx.application import Sphinx
2419

src/scanpydoc/definition_list_typed_field.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020

2121

2222
if TYPE_CHECKING:
23-
from typing import Any, TypeAlias
23+
from typing import Any
2424
from collections.abc import Iterable
2525

2626
from sphinx.application import Sphinx
2727
from sphinx.environment import BuildEnvironment
2828

29-
TextLikeNode: TypeAlias = nodes.Text | nodes.TextElement
29+
type TextLikeNode = nodes.Text | nodes.TextElement
3030

3131

3232
class DLTypedField(PyTypedField):
@@ -98,12 +98,10 @@ def handle_item(
9898
@_setup_sig
9999
def setup(app: Sphinx) -> dict[str, Any]:
100100
"""Replace :class:`~sphinx.domains.python.PyTypedField` with ours."""
101-
napoleon_requested = "sphinx.ext.napoleon" in app.config.extensions
102-
napoleon_loaded = next(
103-
(True for ft in PyObject.doc_field_types if ft.name == "keyword"),
104-
False,
105-
)
106-
if napoleon_requested and not napoleon_loaded:
101+
if (
102+
"sphinx.ext.napoleon" in app.config.extensions
103+
and "sphinx.ext.napoleon" not in app.extensions
104+
):
107105
msg = f"Please load sphinx.ext.napoleon before {__name__}"
108106
raise RuntimeError(msg)
109107

src/scanpydoc/elegant_typehints/_formatting.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import inspect
44
from types import GenericAlias
5-
from typing import TYPE_CHECKING, cast, get_args, get_origin
5+
from typing import TYPE_CHECKING, TypeAliasType, cast, get_args, get_origin
66

77
from sphinx_autodoc_typehints import format_annotation
88

@@ -16,7 +16,7 @@
1616
from sphinx.config import Config
1717

1818

19-
def typehints_formatter(annotation: type[Any], config: Config) -> str | None:
19+
def typehints_formatter(annotation: object, config: Config) -> str | None:
2020
"""Generate reStructuredText containing links to the types.
2121
2222
Can be used as ``typehints_formatter`` for :mod:`sphinx_autodoc_typehints`,
@@ -33,6 +33,9 @@ def typehints_formatter(annotation: type[Any], config: Config) -> str | None:
3333
-------
3434
reStructuredText describing the type
3535
"""
36+
if isinstance(annotation, TypeAliasType):
37+
return format_annotation(annotation.__value__, config)
38+
3639
if inspect.isclass(annotation) and annotation.__module__ == "builtins":
3740
return None
3841

src/scanpydoc/elegant_typehints/_role_mapping.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def __getitem__(self, key: tuple[str | None, str]) -> tuple[str | None, str]:
5050
for known_role in chain([None], {r for r, _ in self}):
5151
try:
5252
return self.data[known_role, key[1]]
53-
except KeyError: # noqa: PERF203
53+
except KeyError:
5454
pass
5555
raise KeyError(key)
5656

src/scanpydoc/rtd_github_links/__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@
7575

7676
if TYPE_CHECKING:
7777
from types import CodeType, FrameType, MethodType, FunctionType, TracebackType
78-
from typing import Any, TypeAlias
78+
from typing import Any
7979
from collections.abc import Callable
8080

81-
_SourceObjectType: TypeAlias = (
81+
type _SourceObjectType = (
8282
ModuleType
8383
| type[Any]
8484
| MethodType
@@ -211,8 +211,7 @@ def github_url(qualname: str) -> str:
211211
try:
212212
obj, module = _get_obj_module(qualname)
213213
except Exception as e:
214-
if sys.version_info >= (3, 11):
215-
e.add_note(f"Qualname: {qualname!r}")
214+
e.add_note(f"Qualname: {qualname!r}")
216215
raise
217216
assert rtd_links_prefix is not None # noqa: S101
218217
path = rtd_links_prefix / _module_path(obj, module)

0 commit comments

Comments
 (0)