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
« 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
36from docutils import nodes
37from pyTooling.Decorators import export
38from sphinx.application import Sphinx
39from sphinx.config import Config
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
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
56 option_spec = {
57 "package": strip
58 }
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.
66 _packageName: str
68 _distribution: Distribution
70 def _CheckOptions(self) -> None:
71 """
72 Parse all directive options or use default values.
73 """
74 self._packageName = self._ParseStringOption("package")
76 @classmethod
77 def CheckConfiguration(cls, sphinxApplication: Sphinx, sphinxConfiguration: Config) -> None:
78 """
79 Check configuration fields and load necessary values.
81 :param sphinxApplication: Sphinx application instance.
82 :param sphinxConfiguration: Sphinx configuration instance.
83 """
84 pass
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 ]
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
102 # def sortedValues(d: Mapping[str, Testsuite]) -> Generator[Testsuite, None, None]:
103 # for key in sorted(d.keys()):
104 # yield d[key]
106 def renderRoot(tableBody: nodes.tbody, distribution: Distribution) -> None:
107 tableRow = nodes.row("", classes=["report-dependency-table-row", "report-dependency"])
108 tableBody += tableRow
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}"))
114 # for ts in sortedValues(testsuite._testsuites):
115 # renderTestsuite(tableBody, ts, 0)
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%}")),
170 renderRoot(tableBody, self._distribution)
172 # # Add a summary row
174 return table
176 def run(self) -> List[nodes.Node]:
177 self._CheckOptions()
179 # Assemble a list of Python source files
180 scanner = DependencyScanner(self._packageName)
181 self._distribution = scanner.Distribution
183 container = nodes.container()
184 container += self._GenerateDependencyTable()
186 return [container]