Coverage for src/_griffe/docstrings/parsers.py: 56.10%

31 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-08-15 16:47 +0200

1# This module imports all the defined parsers 

2# and provides a generic function to parse docstrings. 

3 

4from __future__ import annotations 

5 

6from typing import TYPE_CHECKING, Any, Callable, Literal 

7 

8from _griffe.docstrings.google import parse_google 

9from _griffe.docstrings.models import DocstringSection, DocstringSectionText 

10from _griffe.docstrings.numpy import parse_numpy 

11from _griffe.docstrings.sphinx import parse_sphinx 

12from _griffe.enumerations import Parser 

13 

14if TYPE_CHECKING: 

15 from _griffe.models import Docstring 

16 

17 

18# This is not our preferred order, but the safest order for proper detection 

19# using heuristics. Indeed, Google style sections sometimes appear in otherwise 

20# plain markup docstrings, which could lead to false positives. Same for Numpy 

21# sections, whose syntax is regular rST markup, and which can therefore appear 

22# in plain markup docstrings too, even more often than Google sections. 

23_default_style_order = [Parser.sphinx, Parser.google, Parser.numpy] 

24 

25 

26DocstringStyle = Literal["google", "numpy", "sphinx", "auto"] 

27"""The supported docstring styles (literal values of the Parser enumeration).""" 

28DocstringDetectionMethod = Literal["heuristics", "max_sections"] 

29"""The supported methods to infer docstring styles.""" 

30 

31 

32def infer_docstring_style( 

33 docstring: Docstring, # noqa: ARG001 

34 *, 

35 method: DocstringDetectionMethod = "heuristics", # noqa: ARG001 

36 style_order: list[Parser] | list[DocstringStyle] | None = None, 

37 default: Parser | DocstringStyle | None = None, 

38 **options: Any, # noqa: ARG001 

39) -> tuple[Parser | None, list[DocstringSection] | None]: 

40 """Infer the parser to use for the docstring. 

41 

42 [:octicons-heart-fill-24:{ .pulse } Sponsors only](../../../insiders/index.md){ .insiders } — 

43 [:octicons-tag-24: Insiders 1.3.0](../../../insiders/changelog.md#1.3.0). 

44 

45 The 'heuristics' method uses regular expressions. The 'max_sections' method 

46 parses the docstring with all parsers specified in `style_order` and returns 

47 the one who parsed the most sections. 

48 

49 If heuristics fail, the `default` parser is returned. If multiple parsers 

50 parsed the same number of sections, `style_order` is used to decide which 

51 one to return. The `default` parser is never used with the 'max_sections' method. 

52 

53 For non-Insiders versions, `default` is returned if specified, else the first 

54 parser in `style_order` is returned. If `style_order` is not specified, 

55 `None` is returned. 

56 

57 Additional options are parsed to the detected parser, if any. 

58 

59 Parameters: 

60 docstring: The docstring to parse. 

61 method: The method to use to infer the parser. 

62 style_order: The order of the styles to try when inferring the parser. 

63 default: The default parser to use if the inference fails. 

64 **options: Additional parsing options. 

65 

66 Returns: 

67 The inferred parser, and optionally parsed sections (when method is 'max_sections'). 

68 """ 

69 if default: 

70 return default if isinstance(default, Parser) else Parser(default), None 

71 if style_order: 

72 style = style_order[0] 

73 return style if isinstance(style, Parser) else Parser(style), None 

74 return None, None 

75 

76 

77def parse_auto( 

78 docstring: Docstring, 

79 *, 

80 method: DocstringDetectionMethod = "heuristics", 

81 style_order: list[Parser] | list[DocstringStyle] | None = None, 

82 default: Parser | DocstringStyle | None = None, 

83 **options: Any, 

84) -> list[DocstringSection]: 

85 """Parse a docstring by automatically detecting the style it uses. 

86 

87 [:octicons-heart-fill-24:{ .pulse } Sponsors only](../../../insiders/index.md){ .insiders } — 

88 [:octicons-tag-24: Insiders 1.3.0](../../../insiders/changelog.md#1.3.0). 

89 

90 See [`infer_docstring_style`][griffe.infer_docstring_style] for more information 

91 on the available parameters. 

92 

93 Parameters: 

94 docstring: The docstring to parse. 

95 method: The method to use to infer the parser. 

96 style_order: The order of the styles to try when inferring the parser. 

97 default: The default parser to use if the inference fails. 

98 **options: Additional parsing options. 

99 

100 Returns: 

101 A list of docstring sections. 

102 """ 

103 style, sections = infer_docstring_style( 

104 docstring, 

105 method=method, 

106 style_order=style_order, 

107 default=default, 

108 **options, 

109 ) 

110 if sections is None: 

111 return parse(docstring, style, **options) 

112 return sections 

113 

114 

115parsers: dict[Parser, Callable[[Docstring], list[DocstringSection]]] = { 

116 Parser.auto: parse_auto, 

117 Parser.google: parse_google, 

118 Parser.sphinx: parse_sphinx, 

119 Parser.numpy: parse_numpy, 

120} 

121 

122 

123def parse( 

124 docstring: Docstring, 

125 parser: DocstringStyle | Parser | None, 

126 **options: Any, 

127) -> list[DocstringSection]: 

128 """Parse the docstring. 

129 

130 Parameters: 

131 docstring: The docstring to parse. 

132 parser: The docstring parser to use. If None, return a single text section. 

133 **options: The options accepted by the parser. 

134 

135 Returns: 

136 A list of docstring sections. 

137 """ 

138 if parser: 

139 if not isinstance(parser, Parser): 139 ↛ 140line 139 didn't jump to line 140 because the condition on line 139 was never true

140 parser = Parser(parser) 

141 return parsers[parser](docstring, **options) 

142 return [DocstringSectionText(docstring.value)]