Coverage for sphinx_reports/Dependency.py: 56%

45 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-05-09 22:12 +0000

1# ==================================================================================================================== # 

2# _ _ _ # 

3# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # 

4# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # 

5# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # 

6# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # 

7# |_| |_| # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2023-2025 Patrick Lehmann - Bötzingen, Germany # 

15# # 

16# Licensed under the Apache License, Version 2.0 (the "License"); # 

17# you may not use this file except in compliance with the License. # 

18# You may obtain a copy of the License at # 

19# # 

20# http://www.apache.org/licenses/LICENSE-2.0 # 

21# # 

22# Unless required by applicable law or agreed to in writing, software # 

23# distributed under the License is distributed on an "AS IS" BASIS, # 

24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

25# See the License for the specific language governing permissions and # 

26# limitations under the License. # 

27# # 

28# SPDX-License-Identifier: Apache-2.0 # 

29# ==================================================================================================================== # 

30# 

31""" 

32**Report unit test results as Sphinx documentation page(s).** 

33""" 

34from typing import Dict, Tuple, Any, List, Mapping, Generator 

35 

36from docutils import nodes 

37from pyTooling.Decorators import export 

38from sphinx.application import Sphinx 

39from sphinx.config import Config 

40 

41from sphinx_reports.Common import ReportExtensionError 

42from sphinx_reports.Sphinx import strip, BaseDirective 

43from sphinx_reports.DataModel.Dependency import Distribution 

44from sphinx_reports.Adapter.Dependency import DependencyScanner 

45 

46 

47@export 

48class DependencyTable(BaseDirective): 

49 """ 

50 This directive will be replaced by a table representing dependencies. 

51 """ 

52 has_content = False 

53 required_arguments = 0 

54 optional_arguments = 1 

55 

56 option_spec = { 

57 "package": strip 

58 } 

59 

60 directiveName: str = "dependency-table" 

61 configPrefix: str = "dep" 

62 configValues: Dict[str, Tuple[Any, str, Any]] = { 

63 # f"{configPrefix}_testsuites": ({}, "env", Dict) 

64 } #: A dictionary of all configuration values used by unittest directives. 

65 

66 _packageName: str 

67 

68 _distribution: Distribution 

69 

70 def _CheckOptions(self) -> None: 

71 """ 

72 Parse all directive options or use default values. 

73 """ 

74 self._packageName = self._ParseStringOption("package") 

75 

76 @classmethod 

77 def CheckConfiguration(cls, sphinxApplication: Sphinx, sphinxConfiguration: Config) -> None: 

78 """ 

79 Check configuration fields and load necessary values. 

80 

81 :param sphinxApplication: Sphinx application instance. 

82 :param sphinxConfiguration: Sphinx configuration instance. 

83 """ 

84 pass 

85 

86 def _GenerateDependencyTable(self) -> nodes.table: 

87 # Create a table and table header with 8 columns 

88 columns = [ 

89 ("Package", None, 500), 

90 ("Version", None, 100), 

91 ("License", None, 100), 

92 ] 

93 

94 table, tableGroup = self._CreateTableHeader( 

95 identifier=self._packageName, 

96 columns=columns, 

97 classes=["report-dependency-table"] 

98 ) 

99 tableBody = nodes.tbody() 

100 tableGroup += tableBody 

101 

102 # def sortedValues(d: Mapping[str, Testsuite]) -> Generator[Testsuite, None, None]: 

103 # for key in sorted(d.keys()): 

104 # yield d[key] 

105 

106 def renderRoot(tableBody: nodes.tbody, distribution: Distribution) -> None: 

107 tableRow = nodes.row("", classes=["report-dependency-table-row", "report-dependency"]) 

108 tableBody += tableRow 

109 

110 tableRow += nodes.entry("", nodes.paragraph(text=f"{distribution.Name}")) 

111 tableRow += nodes.entry("", nodes.paragraph(text=f"{distribution.Version}")) 

112 tableRow += nodes.entry("", nodes.paragraph(text=f"{distribution.Licenses}")) 

113 

114 # for ts in sortedValues(testsuite._testsuites): 

115 # renderTestsuite(tableBody, ts, 0) 

116 

117 # def renderTestsuite(tableBody: nodes.tbody, testsuite: Testsuite, level: int) -> None: 

118 # state = stateToSymbol(testsuite._state) 

119 # 

120 # tableRow = nodes.row("", classes=["report-unittest-table-row", "report-testsuite"]) 

121 # tableBody += tableRow 

122 # 

123 # tableRow += nodes.entry("", nodes.paragraph(text=f"{'  ' * level}{state}{testsuite.Name}")) 

124 # tableRow += nodes.entry("", nodes.paragraph(text=f"{testsuite.Tests}")) 

125 # tableRow += nodes.entry("", nodes.paragraph(text=f"{testsuite.Skipped}")) 

126 # tableRow += nodes.entry("", nodes.paragraph(text=f"{testsuite.Errored}")) 

127 # tableRow += nodes.entry("", nodes.paragraph(text=f"{testsuite.Failed}")) 

128 # tableRow += nodes.entry("", nodes.paragraph(text=f"{testsuite.Passed}")) 

129 # if not self._noAssertions: 

130 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {testsuite.Uncovered}")), 

131 # tableRow += nodes.entry("", nodes.paragraph(text=f"{timeformat(testsuite.Time)}")) 

132 # 

133 # for ts in sortedValues(testsuite._testsuites): 

134 # renderTestsuite(tableBody, ts, level + 1) 

135 # 

136 # for testcase in sortedValues(testsuite._testcases): 

137 # renderTestcase(tableBody, testcase, level + 1) 

138 # 

139 # def renderTestcase(tableBody: nodes.tbody, testcase: Testcase, level: int) -> None: 

140 # state = stateToSymbol(testcase._state) 

141 # 

142 # tableRow = nodes.row("", classes=["report-unittest-table-row", "report-testcase"]) 

143 # tableBody += tableRow 

144 # 

145 # tableRow += nodes.entry("", nodes.paragraph(text=f"{'  ' * level}{state}{testcase.Name}")) 

146 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {testsuite.Expected}")), 

147 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {testsuite.Covered}")), 

148 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {testsuite.Uncovered}")), 

149 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {testsuite.Uncovered}")), 

150 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {testsuite.Uncovered}")), 

151 # if not self._noAssertions: 

152 # tableRow += nodes.entry("", nodes.paragraph(text=f"{testcase.Assertions}")) 

153 # tableRow += nodes.entry("", nodes.paragraph(text=f"{timeformat(testcase.Time)}")) 

154 # 

155 # for test in sortedValues(testcase._tests): 

156 # state = stateToSymbol(test._state) 

157 # tableRow = nodes.row("", classes=["report-unittest-table-row", "report-test"]) 

158 # tableBody += tableRow 

159 # 

160 # tableRow += nodes.entry("", nodes.paragraph(text=f"{'  ' * (level + 1)}{state}{test.Name}")) 

161 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Expected}")), 

162 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Covered}")), 

163 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Covered}")), 

164 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Covered}")), 

165 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Covered}")), 

166 # if not self._noAssertions: 

167 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Uncovered}")), 

168 # tableRow += nodes.entry("", nodes.paragraph(text=f"")) # {test.Coverage :.1%}")), 

169 

170 renderRoot(tableBody, self._distribution) 

171 

172 # # Add a summary row 

173 

174 return table 

175 

176 def run(self) -> List[nodes.Node]: 

177 self._CheckOptions() 

178 

179 # Assemble a list of Python source files 

180 scanner = DependencyScanner(self._packageName) 

181 self._distribution = scanner.Distribution 

182 

183 container = nodes.container() 

184 container += self._GenerateDependencyTable() 

185 

186 return [container]