File: helpers.py

package info (click to toggle)
python-griffe 1.14.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,256 kB
  • sloc: python: 16,348; javascript: 84; makefile: 47; sh: 24
file content (73 lines) | stat: -rw-r--r-- 2,194 bytes parent folder | download | duplicates (2)
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
71
72
73
"""This module contains helpers for testing docstring parsing."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Protocol, Union

from griffe import (
    Attribute,
    Class,
    Docstring,
    DocstringSection,
    Function,
    LogLevel,
    Module,
)

if TYPE_CHECKING:
    from collections.abc import Iterator
    from types import ModuleType


ParentType = Union[Module, Class, Function, Attribute, None]
ParseResultType = tuple[list[DocstringSection], list[str]]


class ParserType(Protocol):  # noqa: D101
    def __call__(  # noqa: D102
        self,
        docstring: str,
        parent: ParentType | None = None,
        **parser_opts: Any,
    ) -> ParseResultType: ...


def parser(parser_module: ModuleType) -> Iterator[ParserType]:
    """Wrap a parser to help testing.

    Parameters:
        parser_module: The parser module containing a `parse` function.

    Yields:
        The wrapped function.
    """
    original_warn = parser_module.docstring_warning

    def parse(docstring: str, parent: ParentType | None = None, **parser_opts: Any) -> ParseResultType:
        """Parse a docstring.

        Parameters:
            docstring: The docstring to parse.
            parent: The docstring's parent object.
            **parser_opts: Additional options accepted by the parser.

        Returns:
            The parsed sections, and warnings.
        """
        docstring_object = Docstring(docstring, lineno=1, endlineno=None)
        docstring_object.endlineno = len(docstring_object.lines) + 1
        if parent is not None:
            docstring_object.parent = parent
            parent.docstring = docstring_object
        warnings = []
        parser_module.docstring_warning = (  # type: ignore[attr-defined]
            lambda _docstring, _offset, message, log_level=LogLevel.warning: warnings.append(message)
        )
        func_name = f"parse_{parser_module.__name__.split('.')[-1]}"
        func = getattr(parser_module, func_name)
        sections = func(docstring_object, **parser_opts)
        return sections, warnings

    yield parse

    parser_module.docstring_warning = original_warn  # type: ignore[attr-defined]