Skip to content

Commit f1672f7

Browse files
Fix for issue #47
1 parent cf69260 commit f1672f7

File tree

9 files changed

+74
-5
lines changed

9 files changed

+74
-5
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
*Note that versions roughly correspond to the version of mkdocstrings-python that they
44
are compatible with.*
55

6+
## 1.16.4
7+
8+
* Fix handling of aliases (see bug #47)
9+
610
## 1.16.3
711

812
* Added `check_crossrefs_exclude` config option

pixi.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ dynamic = ["version"]
2626
requires-python = ">=3.9"
2727
dependencies = [
2828
"mkdocstrings-python >=1.16.6,<2.0",
29-
"griffe >=1.0"
29+
"griffe >=1.0",
3030
]
3131

3232
[project.urls]
@@ -47,7 +47,7 @@ dev = [
4747
"mike >=1.1",
4848
"mkdocs >=1.5.3,<2.0",
4949
"mkdocs-material >=9.5.4",
50-
"linkchecker >=10.4"
50+
"linkchecker >=10.4",
5151
]
5252

5353
[tool.pixi.workspace]

src/mkdocstrings_handlers/python_xref/crossref.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import sys
2121
from typing import Any, Callable, List, Optional, cast
2222

23-
from griffe import Docstring, Object
23+
from griffe import Alias, Docstring, GriffeError, Object
2424
from mkdocstrings import get_logger
2525

2626
__all__ = [
@@ -332,6 +332,13 @@ def substitute_relative_crossrefs(obj: Object, checkref: Optional[Callable[[str]
332332
doc.value = _RE_CROSSREF.sub(_RelativeCrossrefProcessor(doc, checkref=checkref), doc.value)
333333

334334
for member in obj.members.values():
335+
if isinstance(member, Alias):
336+
try:
337+
member = member.target
338+
except GriffeError as ex:
339+
# If alias could not be resolved, it probably refers
340+
# to an external package, not be documented.
341+
pass
335342
if isinstance(member, Object): # pragma: no branch
336343
substitute_relative_crossrefs(member, checkref=checkref)
337344

tests/project/src/myproj/bar.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
class Bar(Foo):
2222
"""See [bar][.] method."""
2323

24+
attribute: str = "attribute"
25+
"""
26+
See [`foo`][(c).]
27+
"""
28+
2429
def bar(self) -> None:
2530
"""This is in the [Bar][(c)] class.
2631
Also see the [foo][^.] method and the [func][(m).] function.

tests/project/src/myproj/pkg/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
A module
1616
"""
1717

18+
from .dataclass import Dataclass
19+
20+
__all__ = [
21+
"Dataclass",
22+
"func",
23+
]
24+
1825
def func() -> None:
1926
"""
2027
A function
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
from dataclasses import dataclass, field
3+
4+
@dataclass
5+
class Dataclass:
6+
"""
7+
Test dataclasses
8+
9+
See [content][(c).] for an example attribute.
10+
11+
See [method][(c).]
12+
"""
13+
content: str = "hi"
14+
"""some content"""
15+
16+
duration: float = field(default_factory=lambda: 0.0)
17+
"""
18+
example: [`content`][(c).]
19+
"""
20+
21+
def method(self) -> str:
22+
"""Example method."""

tests/test_crossref.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from textwrap import dedent
2424
from typing import Callable, Optional
2525

26+
import griffe
2627
import pytest
2728
from griffe import Class, Docstring, Function, Module, Object, LinesCollection
2829

@@ -264,3 +265,13 @@ def test_doc_value_offset_to_location() -> None:
264265

265266
assert doc_value_offset_to_location(doc3, 0) == (2, 5)
266267
assert doc_value_offset_to_location(doc3, 6) == (3, 3)
268+
269+
def test_griffe() -> None:
270+
this_dir = Path(__file__).parent
271+
test_src_dir = this_dir / "project" / "src"
272+
myproj = griffe.load(
273+
"myproj",
274+
search_paths = [ test_src_dir ],
275+
)
276+
substitute_relative_crossrefs(myproj)
277+
print(myproj)

tests/test_integration.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def check_autorefs(autorefs: List[Any], cases: Dict[Tuple[str,str],str] ) -> Non
3636
Arguments:
3737
autorefs: list of autoref tags parsed from HTML
3838
cases: mapping from (<location>,<title>) to generated reference tag
39-
where <location? is the qualified name of the object whose doc string
39+
where <location> is the qualified name of the object whose doc string
4040
contains the cross-reference, and <title> is the text in the cross-reference.
4141
"""
4242
cases = cases.copy()
@@ -123,4 +123,17 @@ def test_integration(tmpdir: PathLike) -> None:
123123
}
124124
)
125125

126+
pkg_html = site_dir.joinpath('pkg', 'index.html').read_text()
127+
pkg_bs = bs4.BeautifulSoup(pkg_html, 'html.parser')
126128

129+
autorefs = pkg_bs.find_all('a', attrs={'class':'autorefs'})
130+
assert len(autorefs) >= 3
131+
132+
check_autorefs(
133+
autorefs,
134+
{
135+
('myproj.pkg.Dataclass', 'content') : '#myproj.pkg.Dataclass.content',
136+
('myproj.pkg.Dataclass', 'method') : '#myproj.pkg.Dataclass.method',
137+
('myproj.pkg.Dataclass.duration', 'content') : '#myproj.pkg.Dataclass.content',
138+
}
139+
)

0 commit comments

Comments
 (0)