File: test_safe_parse.py

package info (click to toggle)
sphinx-autodoc-typehints 3.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 684 kB
  • sloc: python: 5,081; makefile: 3
file content (70 lines) | stat: -rw-r--r-- 1,915 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""Tests that snippet parsing doesn't trigger extension directive side-effects."""

from __future__ import annotations

import sys
from pathlib import Path
from textwrap import dedent
from typing import TYPE_CHECKING, ClassVar

import pytest
from docutils.parsers.rst import Directive, directives

if TYPE_CHECKING:
    from io import StringIO

    from sphinx.testing.util import SphinxTestApp


@pytest.mark.sphinx("text", testroot="integration")
def test_extension_directive_not_executed_during_snippet_parse(
    app: SphinxTestApp,
    status: StringIO,
    warning: StringIO,  # noqa: ARG001
    monkeypatch: pytest.MonkeyPatch,
) -> None:
    """A non-builtin directive in a docstring should only execute once (during the real build)."""
    directives.register_directive("tracking-directive", _TrackingDirective)
    _TrackingDirective.executions.clear()

    (Path(app.srcdir) / "index.rst").write_text(
        dedent("""\
        Test
        ====

        .. autofunction:: mod.func_with_tracking_directive
    """)
    )

    src = dedent("""\
    def func_with_tracking_directive(x: int) -> int:
        \"\"\"Do something.

        :param x: A number.

        .. tracking-directive::

            unique-id-123

        \"\"\"
        return x
    """)
    exec(compile(src, "<test>", "exec"), (mod := {}))  # noqa: S102
    fake_module = type(sys)("mod")
    fake_module.__dict__.update(mod)
    monkeypatch.setitem(sys.modules, "mod", fake_module)

    app.build()
    assert "build succeeded" in status.getvalue()
    assert _TrackingDirective.executions.count("unique-id-123") == 1


class _TrackingDirective(Directive):
    """Directive that records each execution to detect double-processing."""

    has_content = True
    executions: ClassVar[list[str]] = []

    def run(self) -> list:
        _TrackingDirective.executions.append(self.content[0] if self.content else "")
        return []