Skip to content

Commit a79c4c1

Browse files
caffeinepillspre-commit-ci[bot]gaborbernat
authored
Return injection fix (#445)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bernát Gábor <[email protected]>
1 parent 01c9126 commit a79c4c1

File tree

4 files changed

+106
-7
lines changed

4 files changed

+106
-7
lines changed

Diff for: src/sphinx_autodoc_typehints/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -779,6 +779,9 @@ def node_line_no(node: Node) -> int | None:
779779
docutils rst parser source code. An example where the node doesn't have a line number but the first child does is
780780
all `definition_list` nodes. It seems like bullet_list and option_list get line numbers, but enum_list also doesn't.
781781
"""
782+
if node is None:
783+
return None
784+
782785
while node.line is None and node.children:
783786
node = node.children[0]
784787
return node.line

Diff for: src/sphinx_autodoc_typehints/parser.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@
1313

1414
from docutils import nodes
1515
from docutils.frontend import Values
16+
from docutils.statemachine import StringList
17+
18+
19+
class _RstSnippetParser(RSTParser):
20+
@staticmethod
21+
def decorate(_content: StringList) -> None:
22+
"""Override to skip processing rst_epilog/rst_prolog for typing."""
1623

1724

1825
def parse(inputstr: str, settings: Values | optparse.Values) -> nodes.document:
1926
"""Parse inputstr and return a docutils document."""
2027
doc = new_document("", settings=settings)
2128
with sphinx_domains(settings.env):
22-
parser = RSTParser()
29+
parser = _RstSnippetParser()
2330
parser.set_application(settings.env.app)
2431
parser.parse(inputstr, doc)
2532
return doc

Diff for: tests/test_integration.py

+92-5
Original file line numberDiff line numberDiff line change
@@ -1268,14 +1268,100 @@ def typehints_use_signature(a: AsyncGenerator) -> AsyncGenerator:
12681268
return a
12691269

12701270

1271+
prolog = """
1272+
.. |test_node_start| replace:: {test_node_start}
1273+
""".format(test_node_start="test_start")
1274+
1275+
1276+
@expected(
1277+
"""
1278+
mod.docstring_with_multiline_note_after_params_prolog_replace(param)
1279+
1280+
Do something.
1281+
1282+
Parameters:
1283+
**param** ("int") -- A parameter.
1284+
1285+
Return type:
1286+
"None"
1287+
1288+
Note:
1289+
1290+
Some notes. test_start More notes
1291+
1292+
""",
1293+
rst_prolog=prolog,
1294+
)
1295+
def docstring_with_multiline_note_after_params_prolog_replace(param: int) -> None: # noqa: ARG001
1296+
"""Do something.
1297+
1298+
Args:
1299+
param: A parameter.
1300+
1301+
Note:
1302+
1303+
Some notes. |test_node_start|
1304+
More notes
1305+
"""
1306+
1307+
1308+
epilog = """
1309+
.. |test_node_end| replace:: {test_node_end}
1310+
""".format(test_node_end="test_end")
1311+
1312+
1313+
@expected(
1314+
"""
1315+
mod.docstring_with_multiline_note_after_params_epilog_replace(param)
1316+
1317+
Do something.
1318+
1319+
Parameters:
1320+
**param** ("int") -- A parameter.
1321+
1322+
Return type:
1323+
"None"
1324+
1325+
Note:
1326+
1327+
Some notes. test_end More notes
1328+
1329+
""",
1330+
rst_epilog=epilog,
1331+
)
1332+
def docstring_with_multiline_note_after_params_epilog_replace(param: int) -> None: # noqa: ARG001
1333+
"""Do something.
1334+
1335+
Args:
1336+
param: A parameter.
1337+
1338+
Note:
1339+
1340+
Some notes. |test_node_end|
1341+
More notes
1342+
"""
1343+
1344+
1345+
# Config settings for each test run.
1346+
# Config Name: Sphinx Options as Dict.
1347+
configs = {
1348+
"default_conf": {},
1349+
"prolog_conf": {"rst_prolog": prolog},
1350+
"epilog_conf": {
1351+
"rst_epilog": epilog,
1352+
},
1353+
"bothlog_conf": {
1354+
"rst_prolog": prolog,
1355+
"rst_epilog": epilog,
1356+
},
1357+
}
1358+
1359+
12711360
@pytest.mark.parametrize("val", [x for x in globals().values() if hasattr(x, "EXPECTED")])
1361+
@pytest.mark.parametrize("conf_run", ["default_conf", "prolog_conf", "epilog_conf", "bothlog_conf"])
12721362
@pytest.mark.sphinx("text", testroot="integration")
12731363
def test_integration(
1274-
app: SphinxTestApp,
1275-
status: StringIO,
1276-
warning: StringIO,
1277-
monkeypatch: pytest.MonkeyPatch,
1278-
val: Any,
1364+
app: SphinxTestApp, status: StringIO, warning: StringIO, monkeypatch: pytest.MonkeyPatch, val: Any, conf_run: str
12791365
) -> None:
12801366
if isclass(val) and issubclass(val, BaseException):
12811367
template = AUTO_EXCEPTION
@@ -1285,6 +1371,7 @@ def test_integration(
12851371
template = AUTO_FUNCTION
12861372

12871373
(Path(app.srcdir) / "index.rst").write_text(template.format(val.__name__))
1374+
app.config.__dict__.update(configs[conf_run])
12881375
app.config.__dict__.update(val.OPTIONS)
12891376
monkeypatch.setitem(sys.modules, "mod", sys.modules[__name__])
12901377
app.build()

Diff for: tests/test_sphinx_autodoc_typehints.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,9 @@ def test_sphinx_output_default_role(app: SphinxTestApp, status: StringIO) -> Non
607607

608608
assert "build succeeded" in status.getvalue() # Build succeeded
609609

610-
contents_lines = (Path(app.srcdir) / "_build/pseudoxml/simple_default_role.pseudoxml").read_text().splitlines()
610+
contents_lines = (
611+
(Path(app.srcdir) / "_build/pseudoxml/simple_default_role.pseudoxml").read_text(encoding="utf-8").splitlines()
612+
)
611613
list_item_idxs = [i for i, line in enumerate(contents_lines) if line.strip() == "<list_item>"]
612614
foo_param = dedent("\n".join(contents_lines[list_item_idxs[0] : list_item_idxs[1]]))
613615
expected_foo_param = """\

0 commit comments

Comments
 (0)