Skip to content

Commit c5ce2a7

Browse files
authored
Support generics in rtd_github_links (#160)
1 parent f04ca39 commit c5ce2a7

File tree

5 files changed

+47
-7
lines changed

5 files changed

+47
-7
lines changed

src/scanpydoc/_types.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from __future__ import annotations
2+
3+
from typing import Generic, TypeVar
4+
5+
6+
_GenericAlias: type = type(Generic[TypeVar("_")])

src/scanpydoc/elegant_typehints/_formatting.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import sys
44
import inspect
55
from types import GenericAlias
6-
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast, get_args, get_origin
6+
from typing import TYPE_CHECKING, Any, cast, get_args, get_origin
77

88
from sphinx_autodoc_typehints import format_annotation
99

1010
from scanpydoc import elegant_typehints
11+
from scanpydoc._types import _GenericAlias
1112

1213

1314
if TYPE_CHECKING:
@@ -20,9 +21,6 @@
2021
UnionType = None
2122

2223

23-
_GenericAlias: type = type(Generic[TypeVar("_")])
24-
25-
2624
def typehints_formatter(annotation: type[Any], config: Config) -> str | None:
2725
"""Generate reStructuredText containing links to the types.
2826

src/scanpydoc/rtd_github_links/__init__.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
import sys
6363
import inspect
64-
from types import ModuleType
64+
from types import ModuleType, GenericAlias
6565
from typing import TYPE_CHECKING
6666
from pathlib import Path, PurePosixPath
6767
from importlib import import_module
@@ -70,6 +70,7 @@
7070
from jinja2.defaults import DEFAULT_FILTERS # type: ignore[attr-defined]
7171

7272
from scanpydoc import metadata, _setup_sig
73+
from scanpydoc._types import _GenericAlias
7374

7475

7576
if TYPE_CHECKING:
@@ -158,7 +159,7 @@ def _get_obj_module(qualname: str) -> tuple[Any, ModuleType]:
158159
raise e from None
159160
if isinstance(thing, ModuleType): # pragma: no cover
160161
mod = thing
161-
elif is_dataclass(obj):
162+
elif is_dataclass(obj) or isinstance(thing, (GenericAlias, _GenericAlias)):
162163
obj = thing
163164
else:
164165
obj = thing
@@ -186,7 +187,8 @@ def _module_path(obj: _SourceObjectType, module: ModuleType) -> PurePosixPath:
186187
try:
187188
file = Path(inspect.getabsfile(obj))
188189
except TypeError:
189-
file = Path(module.__file__ or "")
190+
# Some don’t have the attribute, some have it set to None
191+
file = Path(getattr(module, "__file__", None) or "")
190192
offset = -1 if file.name == "__init__.py" else 0
191193
parts = module.__name__.split(".")
192194
return PurePosixPath(*file.parts[offset - len(parts) :])

src/scanpydoc/rtd_github_links/_testdata.py

+20
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,31 @@
22

33
from __future__ import annotations
44

5+
from typing import TYPE_CHECKING, Generic, TypeVar
56
from dataclasses import field, dataclass
67

78
from legacy_api_wrap import legacy_api
89

910

11+
if TYPE_CHECKING:
12+
from typing import TypeAlias
13+
14+
15+
_T = TypeVar("_T")
16+
17+
18+
class _G(Generic[_T]):
19+
pass
20+
21+
22+
# make sure that TestGenericClass keeps its __module__
23+
_G.__module__ = "somewhere_else"
24+
25+
26+
TestGenericBuiltin: TypeAlias = list[str]
27+
TestGenericClass: TypeAlias = _G[int]
28+
29+
1030
@dataclass
1131
class TestDataCls:
1232
test_attr: dict[str, str] = field(default_factory=dict)

tests/test_rtd_github_links.py

+14
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,20 @@ def test_get_github_url_error() -> None:
204204
"scanpydoc/rtd_github_links/_testdata.py",
205205
id="anno",
206206
),
207+
pytest.param(
208+
"scanpydoc.rtd_github_links._testdata.TestGenericBuiltin",
209+
_testdata.TestGenericBuiltin,
210+
_testdata,
211+
"scanpydoc/rtd_github_links/_testdata.py",
212+
id="generic_builtin",
213+
),
214+
pytest.param(
215+
"scanpydoc.rtd_github_links._testdata.TestGenericClass",
216+
_testdata.TestGenericClass,
217+
_testdata,
218+
"scanpydoc/rtd_github_links/_testdata.py",
219+
id="generic_class",
220+
),
207221
],
208222
)
209223
def test_get_obj_module_path(

0 commit comments

Comments
 (0)