Coverage for src/_griffe/docstrings/utils.py: 89.29%
26 statements
« prev ^ index » next coverage.py v7.6.2, created at 2024-10-12 01:34 +0200
« prev ^ index » next coverage.py v7.6.2, created at 2024-10-12 01:34 +0200
1# This module contains utilities for docstrings parsers.
3from __future__ import annotations
5from ast import PyCF_ONLY_AST
6from contextlib import suppress
7from typing import TYPE_CHECKING
9from _griffe.enumerations import LogLevel
10from _griffe.exceptions import BuiltinModuleError
11from _griffe.expressions import safe_get_annotation
12from _griffe.logger import logger
14if TYPE_CHECKING:
15 from _griffe.expressions import Expr
16 from _griffe.models import Docstring
19def docstring_warning(
20 docstring: Docstring,
21 offset: int,
22 message: str,
23 log_level: LogLevel = LogLevel.warning,
24) -> None:
25 """Log a warning when parsing a docstring.
27 This function logs a warning message by prefixing it with the filepath and line number.
29 Parameters:
30 docstring: The docstring object.
31 offset: The offset in the docstring lines.
32 message: The message to log.
34 Returns:
35 A function used to log parsing warnings if `name` was passed, else none.
36 """
38 def warn(docstring: Docstring, offset: int, message: str, log_level: LogLevel = LogLevel.warning) -> None:
39 try:
40 prefix = docstring.parent.relative_filepath # type: ignore[union-attr]
41 except (AttributeError, ValueError):
42 prefix = "<module>"
43 except BuiltinModuleError:
44 prefix = f"<module: {docstring.parent.module.name}>" # type: ignore[union-attr]
45 log = getattr(logger, log_level.value)
46 log(f"{prefix}:{(docstring.lineno or 0)+offset}: {message}")
48 warn(docstring, offset, message, log_level)
51def parse_docstring_annotation(
52 annotation: str,
53 docstring: Docstring,
54 log_level: LogLevel = LogLevel.error,
55) -> str | Expr:
56 """Parse a string into a true name or expression that can be resolved later.
58 Parameters:
59 annotation: The annotation to parse.
60 docstring: The docstring in which the annotation appears.
61 The docstring's parent is accessed to bind a resolver to the resulting name/expression.
62 log_level: Log level to use to log a message.
64 Returns:
65 The string unchanged, or a new name or expression.
66 """
67 with suppress(
68 AttributeError, # docstring has no parent that can be used to resolve names
69 SyntaxError, # annotation contains syntax errors
70 ):
71 code = compile(annotation, mode="eval", filename="", flags=PyCF_ONLY_AST, optimize=2)
72 if code.body: # type: ignore[attr-defined] 72 ↛ 79line 72 didn't jump to line 79
73 name_or_expr = safe_get_annotation(
74 code.body, # type: ignore[attr-defined]
75 parent=docstring.parent, # type: ignore[arg-type]
76 log_level=log_level,
77 )
78 return name_or_expr or annotation
79 return annotation