Skip to content

Commit 9b9e3f1

Browse files
authored
Test wraps (#118)
1 parent 70e37b3 commit 9b9e3f1

File tree

3 files changed

+90
-32
lines changed

3 files changed

+90
-32
lines changed

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ test = [
3232
'coverage',
3333
'coverage-rich',
3434
'toml', # coverage-rich’s dep anyconfig 0.13 needs this
35+
'legacy-api-wrap',
3536
]
3637
doc = [
3738
'scanpydoc[typehints,theme]',

src/scanpydoc/rtd_github_links/__init__.py

+1-11
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from typing import TYPE_CHECKING
6565
from pathlib import Path, PurePosixPath
6666
from importlib import import_module
67+
from dataclasses import fields, is_dataclass
6768

6869
from jinja2.defaults import DEFAULT_FILTERS # type: ignore[attr-defined]
6970

@@ -260,14 +261,3 @@ def setup(app: Sphinx) -> dict[str, Any]:
260261
DEFAULT_FILTERS["github_url"] = github_url
261262

262263
return metadata
263-
264-
265-
if True: # test data
266-
from dataclasses import field, fields, dataclass, is_dataclass
267-
268-
@dataclass
269-
class _TestDataCls:
270-
test_attr: dict[str, str] = field(default_factory=dict)
271-
272-
class _TestCls:
273-
test_anno: int

tests/test_rtd_github_links.py

+88-21
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,30 @@
44
import re
55
import sys
66
import textwrap
7+
from types import ModuleType, FunctionType
78
from typing import TYPE_CHECKING
89
from pathlib import Path, PurePosixPath
910
from importlib import import_module
11+
from dataclasses import field, dataclass
1012

1113
import pytest
1214
from sphinx.config import Config
15+
from legacy_api_wrap import legacy_api
1316

17+
import scanpydoc
1418
from scanpydoc import rtd_github_links
1519
from scanpydoc.rtd_github_links import (
1620
github_url,
1721
_infer_vars,
1822
_get_linenos,
1923
_get_obj_module,
2024
)
21-
from scanpydoc.rtd_github_links._linkcode import (
22-
CInfo,
23-
PyInfo,
24-
linkcode_resolve,
25-
)
25+
from scanpydoc.rtd_github_links._linkcode import CInfo, PyInfo, linkcode_resolve
2626

2727

2828
if TYPE_CHECKING:
29-
from types import ModuleType
3029
from typing import Literal
31-
from collections.abc import Callable
30+
from collections.abc import Callable, Generator
3231

3332
from sphinx.application import Sphinx
3433
from _pytest.monkeypatch import MonkeyPatch
@@ -151,10 +150,55 @@ def test_as_function(
151150
assert github_url(f"scanpydoc.{module}.{name}") == f"{prefix}/{obj_path}#L{s}-L{e}"
152151

153152

154-
def test_get_github_url_only_annotation(prefix: PurePosixPath) -> None:
153+
class _TestMod:
154+
modname = "testing.scanpydoc"
155+
156+
@dataclass
157+
class TestDataCls:
158+
test_attr: dict[str, str] = field(default_factory=dict)
159+
160+
class TestCls:
161+
test_anno: int
162+
163+
def test_func(self) -> None: # pragma: no cover
164+
pass
165+
166+
test_func_wrap: Callable[[], None] # is set below
167+
168+
169+
@pytest.fixture()
170+
def test_mod() -> Generator[ModuleType, None, None]:
171+
mod = sys.modules[_TestMod.modname] = ModuleType(_TestMod.modname)
172+
mod.__file__ = str(
173+
Path(scanpydoc.__file__).parent.parent
174+
/ Path(*_TestMod.modname.split("."))
175+
/ "__init__.py"
176+
)
177+
for name, obj in vars(_TestMod).items():
178+
if not isinstance(obj, (type, FunctionType)):
179+
continue
180+
# pretend things are in the same module
181+
if "test_rtd_github_links" in obj.__module__:
182+
obj.__module__ = _TestMod.modname
183+
setattr(mod, name, obj)
184+
185+
mod.test_func_wrap = legacy_api()(mod.test_func) # type: ignore[attr-defined]
186+
187+
try:
188+
yield mod
189+
finally:
190+
sys.modules.pop(_TestMod.modname, None)
191+
192+
193+
def test_get_github_url_only_annotation(
194+
prefix: PurePosixPath,
195+
test_mod: ModuleType, # noqa: ARG001
196+
) -> None:
155197
"""Doesn’t really work but shouldn’t crash either."""
156-
url = github_url("scanpydoc.rtd_github_links._TestCls.test_anno")
157-
assert url == f"{prefix}/rtd_github_links/__init__.py"
198+
url = github_url(f"{_TestMod.modname}.TestCls.test_anno")
199+
assert url == str(
200+
prefix.parent / Path(*_TestMod.modname.split(".")) / "__init__.py"
201+
)
158202

159203

160204
def test_get_github_url_error() -> None:
@@ -165,27 +209,50 @@ def test_get_github_url_error() -> None:
165209

166210

167211
@pytest.mark.parametrize(
168-
("obj_path", "obj", "mod"),
212+
("obj_path", "get_obj", "get_mod"),
169213
[
170-
pytest.param("scanpydoc.indent", textwrap.indent, textwrap, id="reexport"),
171214
pytest.param(
172-
"scanpydoc.rtd_github_links", rtd_github_links, rtd_github_links, id="mod"
215+
"scanpydoc.indent",
216+
lambda _: textwrap.indent,
217+
lambda _: textwrap,
218+
id="reexport",
173219
),
174220
pytest.param(
175-
"scanpydoc.rtd_github_links._TestDataCls.test_attr",
176-
rtd_github_links._TestDataCls.__dataclass_fields__["test_attr"], # noqa: SLF001
177-
rtd_github_links,
221+
"testing.scanpydoc.test_func",
222+
lambda m: m.test_func,
223+
lambda m: m,
224+
id="func",
225+
),
226+
pytest.param(
227+
"testing.scanpydoc.test_func_wrap",
228+
lambda m: m.test_func_wrap,
229+
lambda m: m,
230+
id="wrapper",
231+
),
232+
pytest.param("testing.scanpydoc", lambda m: m, lambda m: m, id="mod"),
233+
pytest.param(
234+
"testing.scanpydoc.TestDataCls.test_attr",
235+
lambda m: m.TestDataCls.__dataclass_fields__["test_attr"],
236+
lambda m: m,
178237
id="dataclass_field",
179238
),
180239
pytest.param(
181-
"scanpydoc.rtd_github_links._TestCls.test_anno", None, rtd_github_links
240+
"testing.scanpydoc.TestCls.test_anno",
241+
lambda _: None,
242+
lambda m: m,
243+
id="anno",
182244
),
183245
],
184246
)
185-
def test_get_obj_module(obj_path: str, obj: object, mod: ModuleType) -> None:
247+
def test_get_obj_module(
248+
test_mod: ModuleType,
249+
obj_path: str,
250+
get_obj: Callable[[ModuleType], object],
251+
get_mod: Callable[[ModuleType], ModuleType],
252+
) -> None:
186253
obj_rcv, mod_rcv = _get_obj_module(obj_path)
187-
assert obj_rcv is obj
188-
assert mod_rcv is mod
254+
assert obj_rcv is get_obj(test_mod)
255+
assert mod_rcv is get_mod(test_mod)
189256

190257

191258
def test_linkdoc(prefix: PurePosixPath) -> None:
@@ -202,5 +269,5 @@ def test_linkdoc(prefix: PurePosixPath) -> None:
202269
("domain", "info"),
203270
[("py", PyInfo(fullname="foo", module="")), ("c", CInfo(names=[]))],
204271
)
205-
def test_linkdoc_skip(domain: Literal[Domain], info: DomainInfo) -> None:
272+
def test_linkcode_skip(domain: Literal[Domain], info: DomainInfo) -> None:
206273
assert linkcode_resolve(domain, info) is None # type: ignore[arg-type]

0 commit comments

Comments
 (0)