Skip to content

Commit

Permalink
Return injection fix (#445)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bernát Gábor <gaborjbernat@gmail.com>
  • Loading branch information
3 people committed Apr 10, 2024
1 parent 01c9126 commit a79c4c1
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/sphinx_autodoc_typehints/__init__.py
Expand Up @@ -779,6 +779,9 @@ def node_line_no(node: Node) -> int | None:
docutils rst parser source code. An example where the node doesn't have a line number but the first child does is
all `definition_list` nodes. It seems like bullet_list and option_list get line numbers, but enum_list also doesn't.
"""
if node is None:
return None

while node.line is None and node.children:
node = node.children[0]
return node.line
Expand Down
9 changes: 8 additions & 1 deletion src/sphinx_autodoc_typehints/parser.py
Expand Up @@ -13,13 +13,20 @@

from docutils import nodes
from docutils.frontend import Values
from docutils.statemachine import StringList


class _RstSnippetParser(RSTParser):
@staticmethod
def decorate(_content: StringList) -> None:
"""Override to skip processing rst_epilog/rst_prolog for typing."""


def parse(inputstr: str, settings: Values | optparse.Values) -> nodes.document:
"""Parse inputstr and return a docutils document."""
doc = new_document("", settings=settings)
with sphinx_domains(settings.env):
parser = RSTParser()
parser = _RstSnippetParser()
parser.set_application(settings.env.app)
parser.parse(inputstr, doc)
return doc
97 changes: 92 additions & 5 deletions tests/test_integration.py
Expand Up @@ -1268,14 +1268,100 @@ def typehints_use_signature(a: AsyncGenerator) -> AsyncGenerator:
return a


prolog = """
.. |test_node_start| replace:: {test_node_start}
""".format(test_node_start="test_start")


@expected(
"""
mod.docstring_with_multiline_note_after_params_prolog_replace(param)
Do something.
Parameters:
**param** ("int") -- A parameter.
Return type:
"None"
Note:
Some notes. test_start More notes
""",
rst_prolog=prolog,
)
def docstring_with_multiline_note_after_params_prolog_replace(param: int) -> None: # noqa: ARG001
"""Do something.
Args:
param: A parameter.
Note:
Some notes. |test_node_start|
More notes
"""


epilog = """
.. |test_node_end| replace:: {test_node_end}
""".format(test_node_end="test_end")


@expected(
"""
mod.docstring_with_multiline_note_after_params_epilog_replace(param)
Do something.
Parameters:
**param** ("int") -- A parameter.
Return type:
"None"
Note:
Some notes. test_end More notes
""",
rst_epilog=epilog,
)
def docstring_with_multiline_note_after_params_epilog_replace(param: int) -> None: # noqa: ARG001
"""Do something.
Args:
param: A parameter.
Note:
Some notes. |test_node_end|
More notes
"""


# Config settings for each test run.
# Config Name: Sphinx Options as Dict.
configs = {
"default_conf": {},
"prolog_conf": {"rst_prolog": prolog},
"epilog_conf": {
"rst_epilog": epilog,
},
"bothlog_conf": {
"rst_prolog": prolog,
"rst_epilog": epilog,
},
}


@pytest.mark.parametrize("val", [x for x in globals().values() if hasattr(x, "EXPECTED")])
@pytest.mark.parametrize("conf_run", ["default_conf", "prolog_conf", "epilog_conf", "bothlog_conf"])
@pytest.mark.sphinx("text", testroot="integration")
def test_integration(
app: SphinxTestApp,
status: StringIO,
warning: StringIO,
monkeypatch: pytest.MonkeyPatch,
val: Any,
app: SphinxTestApp, status: StringIO, warning: StringIO, monkeypatch: pytest.MonkeyPatch, val: Any, conf_run: str
) -> None:
if isclass(val) and issubclass(val, BaseException):
template = AUTO_EXCEPTION
Expand All @@ -1285,6 +1371,7 @@ def test_integration(
template = AUTO_FUNCTION

(Path(app.srcdir) / "index.rst").write_text(template.format(val.__name__))
app.config.__dict__.update(configs[conf_run])
app.config.__dict__.update(val.OPTIONS)
monkeypatch.setitem(sys.modules, "mod", sys.modules[__name__])
app.build()
Expand Down
4 changes: 3 additions & 1 deletion tests/test_sphinx_autodoc_typehints.py
Expand Up @@ -607,7 +607,9 @@ def test_sphinx_output_default_role(app: SphinxTestApp, status: StringIO) -> Non

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

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

0 comments on commit a79c4c1

Please sign in to comment.