From f088eb4a9aab96f9f680be9006c20ed6b4ce002b Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 26 Apr 2026 21:25:49 +0200 Subject: [PATCH 1/8] Bumped dependencies. Updated CI pipeline. --- .github/dependabot.yml | 13 +++++++++++++ .github/workflows/Pipeline.yml | 6 ++++++ README.md | 2 +- dist/requirements.txt | 2 +- doc/Dependency.rst | 8 ++++---- doc/Overview.rst | 4 ++-- doc/conf.py | 2 ++ doc/requirements.txt | 6 +++--- pyproject.toml | 1 - requirements.txt | 4 ++-- sphinx_reports/HTML.py | 0 sphinx_reports/LaTeX.py | 0 sphinx_reports/Node.py | 0 tests/unit/requirements.txt | 2 +- 14 files changed, 35 insertions(+), 15 deletions(-) create mode 100644 sphinx_reports/HTML.py create mode 100644 sphinx_reports/LaTeX.py create mode 100644 sphinx_reports/Node.py diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cd81235b..f852552b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,3 +10,16 @@ updates: - Dependencies schedule: interval: "daily" # Checks on Monday trough Friday. + + # Maintain GitHub Action runners + - package-ecosystem: "github-actions" + directory: "/" + target-branch: dev + commit-message: + prefix: "[Dependabot]" + labels: + - Dependencies + assignees: + - Paebbels + schedule: + interval: "daily" # Checks on Monday trough Friday. diff --git a/.github/workflows/Pipeline.yml b/.github/workflows/Pipeline.yml index a4c71782..ea5b5e67 100644 --- a/.github/workflows/Pipeline.yml +++ b/.github/workflows/Pipeline.yml @@ -7,6 +7,12 @@ on: # Every Friday at 22:00 - rerun pipeline to check for dependency-based issues - cron: '0 22 * * 5' +permissions: + actions: write + contents: write + pages: write + id-token: write + jobs: Pipeline: uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@r7 diff --git a/README.md b/README.md index dbcc72ad..f175bf14 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Sourcecode on GitHub](https://img.shields.io/badge/pyTooling-sphinx--reports-323131.svg?logo=github&longCache=true)](https://github.com/pyTooling/sphinx-reports) [![Sourcecode License](https://img.shields.io/pypi/l/sphinx-reports?longCache=true&style=flat-square&logo=Apache&label=code)](LICENSE.md) [![Documentation](https://img.shields.io/website?longCache=true&style=flat-square&label=pyTooling.github.io%2Fsphinx-reports&logo=GitHub&logoColor=fff&up_color=blueviolet&up_message=Read%20now%20%E2%9E%9A&url=https%3A%2F%2FpyTooling.github.io%2Fsphinx%2Dreports%2Findex.html)](https://pyTooling.github.io/sphinx-reports/) -[![Documentation License](https://img.shields.io/badge/doc-CC--BY%204.0-green?longCache=true&style=flat-square&logo=CreativeCommons&logoColor=fff)](LICENSE.md) +[![Documentation License](https://img.shields.io/badge/doc-CC--BY%204.0-green?longCache=true&style=flat-square&logo=CreativeCommons&logoColor=fff)](doc/Doc-License.rst) [![PyPI](https://img.shields.io/pypi/v/sphinx-reports?longCache=true&style=flat-square&logo=PyPI&logoColor=FBE072)](https://pypi.org/project/sphinx-reports/) ![PyPI - Status](https://img.shields.io/pypi/status/sphinx-reports?longCache=true&style=flat-square&logo=PyPI&logoColor=FBE072) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/sphinx-reports?longCache=true&style=flat-square&logo=PyPI&logoColor=FBE072) diff --git a/dist/requirements.txt b/dist/requirements.txt index e87980bd..fc810d11 100644 --- a/dist/requirements.txt +++ b/dist/requirements.txt @@ -1,2 +1,2 @@ -wheel ~= 0.45.0 +wheel ~= 0.46.3 twine ~= 6.2 diff --git a/doc/Dependency.rst b/doc/Dependency.rst index 5e477e6b..18edd486 100644 --- a/doc/Dependency.rst +++ b/doc/Dependency.rst @@ -104,7 +104,7 @@ the mandatory dependencies too. +=====================================================================+=============+========================================================================================+======================+ | `pytest `__ | ≥9.0 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ -| `pytest-cov `__ | ≥7.0 | `MIT `__ | *Not yet evaluated.* | +| `pytest-cov `__ | ≥7.1 | `MIT `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ | `Coverage `__ | ≥7.13 | `Apache License, 2.0 `__ | *Not yet evaluated.* | +---------------------------------------------------------------------+-------------+----------------------------------------------------------------------------------------+----------------------+ @@ -154,7 +154,7 @@ the mandatory dependencies too. +=================================================================================================+==============+==========================================================================================================+======================================================================================================================================================+ | `pyTooling `__ | ≥8.11 | `Apache License, 2.0 `__ | *None* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `Sphinx `__ | ≥9.0 | `BSD 3-Clause `__ | *Not yet evaluated.* | +| `Sphinx `__ | ≥9.1 | `BSD 3-Clause `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | `sphinx_rtd_theme `__ | ≥3.1 | `MIT `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -162,11 +162,11 @@ the mandatory dependencies too. +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | `autoapi `__ | ≥2.0.1 | `Apache License, 2.0 `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `sphinx_design `__ | ≥0.6 | `MIT `__ | *Not yet evaluated.* | +| `sphinx_design `__ | ≥0.7 | `MIT `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ | `sphinx-copybutton `__ | ≥0.5 | `MIT `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ -| `sphinx_autodoc_typehints `__ | ≥3.6 | `MIT `__ | *Not yet evaluated.* | +| `sphinx_autodoc_typehints `__ | ≥3.10 | `MIT `__ | *Not yet evaluated.* | +-------------------------------------------------------------------------------------------------+--------------+----------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ .. TODO:: document the usage of diff --git a/doc/Overview.rst b/doc/Overview.rst index c88b872f..d39df681 100644 --- a/doc/Overview.rst +++ b/doc/Overview.rst @@ -47,8 +47,8 @@ See the following :file:`doc/requirements.txt` file as an example with commonly sphinxcontrib-mermaid ~= 2.0 autoapi ~= 2.0.1 sphinx_design ~= 0.7.0 - sphinx-copybutton ~= 0.5.0 - sphinx_autodoc_typehints ~= 3.6 + sphinx-copybutton ~= 0.5.2 + sphinx_autodoc_typehints ~= 3.10 sphinx_reports ~= 1.0 # <= new entry Finally, the extension needs to be enabled in Sphinx's :file:`conf.py`, so the extension is loaded by Sphinx. diff --git a/doc/conf.py b/doc/conf.py index 268341eb..dd2083ed 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -233,6 +233,8 @@ # ============================================================================== # SphinxContrib.Mermaid # ============================================================================== +mermaid_cmd = "mmdc" +mermaid_cmd_shell = True mermaid_params = [ '--backgroundColor', 'transparent', ] diff --git a/doc/requirements.txt b/doc/requirements.txt index 485b36e0..401dbde8 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,7 +1,7 @@ -r ../requirements.txt # Enforce latest version on ReadTheDocs -#sphinx >= 9.0, < 10.0 +#sphinx >= 9.1, < 10.0 #docutils >= 0.22.0 #docutils_stubs ~= 0.0.22 @@ -12,5 +12,5 @@ sphinx_rtd_theme ~= 3.1 sphinxcontrib-mermaid ~= 2.0 autoapi ~= 2.0.1 sphinx_design ~= 0.7.0 -sphinx-copybutton ~= 0.5.0 -sphinx_autodoc_typehints ~= 3.6 +sphinx-copybutton ~= 0.5.2 +sphinx_autodoc_typehints ~= 3.10 diff --git a/pyproject.toml b/pyproject.toml index f3eca8a2..9daae46f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,6 @@ [build-system] requires = [ "setuptools >= 80.0", - "wheel ~= 0.45.0", "pyTooling ~= 8.11" ] build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt index 6f30248b..13990044 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ pyTooling >= 8.0 -pyEDAA.Reports ~= 0.17.0 -sphinx >= 9.0, < 10.0 +pyEDAA.Reports ~= 0.17.3 +sphinx >= 9.1, < 10.0 docutils >= 0.22.0 docutils_stubs >= 0.0.22 diff --git a/sphinx_reports/HTML.py b/sphinx_reports/HTML.py new file mode 100644 index 00000000..e69de29b diff --git a/sphinx_reports/LaTeX.py b/sphinx_reports/LaTeX.py new file mode 100644 index 00000000..e69de29b diff --git a/sphinx_reports/Node.py b/sphinx_reports/Node.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/requirements.txt b/tests/unit/requirements.txt index a2ffbaa9..b20db853 100644 --- a/tests/unit/requirements.txt +++ b/tests/unit/requirements.txt @@ -5,4 +5,4 @@ Coverage ~= 7.13 # Test Runner pytest ~= 9.0 -pytest-cov ~= 7.0 +pytest-cov ~= 7.1 From 063e65208cf93102e52b63e1e64c5d5a9377d7bf Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 26 Apr 2026 21:28:27 +0200 Subject: [PATCH 2/8] Added LandscapeNode and support for landscape pages in PDFs for big unittest reports. --- sphinx_reports/Common.py | 6 +++- sphinx_reports/HTML.py | 67 ++++++++++++++++++++++++++++++++++++ sphinx_reports/LaTeX.py | 70 ++++++++++++++++++++++++++++++++++++++ sphinx_reports/Node.py | 40 ++++++++++++++++++++++ sphinx_reports/Unittest.py | 15 ++++---- sphinx_reports/__init__.py | 44 ++++++++++++++++++++---- 6 files changed, 227 insertions(+), 15 deletions(-) diff --git a/sphinx_reports/Common.py b/sphinx_reports/Common.py index e34875b3..29b6fc8c 100644 --- a/sphinx_reports/Common.py +++ b/sphinx_reports/Common.py @@ -32,12 +32,16 @@ **Common exceptions, classes and helper functions.** """ from enum import Flag -from typing import List +from typing import Callable, Any from pyTooling.Decorators import export from sphinx.errors import ExtensionError +type visitFunc = Callable[[Any, Any], Any] +type departFunc = Callable[[Any, Any], Any] + + @export class ReportExtensionError(ExtensionError): pass diff --git a/sphinx_reports/HTML.py b/sphinx_reports/HTML.py index e69de29b..44efc776 100644 --- a/sphinx_reports/HTML.py +++ b/sphinx_reports/HTML.py @@ -0,0 +1,67 @@ +# ==================================================================================================================== # +# _ _ _ # +# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # +# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # +# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # +# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # +# |_| |_| # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2026-2026 Patrick Lehmann - Bötzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +from typing import Tuple + +from sphinx.writers.html5 import HTML5Translator + +from pyTooling.Decorators import export +from sphinx_reports.Common import visitFunc, departFunc +from sphinx_reports.Node import Landscape + + +__all__ = ["translateLandscape"] + +@export +def visit_Landscape(translator: HTML5Translator, node: Landscape) -> None: + """ + Call back function for visiting a :class:`Landscape`. + + This function has no actions for HTML5. + + :param translator: The HTML5 translator instance. + :param node: The current node being visited. + """ + + +@export +def depart_Landscape(translator: HTML5Translator, node: Landscape) -> None: + """ + Call back function for departing a :class:`Landscape`. + + This function has no actions for HTML5. + + :param translator: The HTML5 translator instance. + :param node: The current node being departed. + """ + + +translateLandscape: Tuple[visitFunc, departFunc] = (visit_Landscape, depart_Landscape) +"""A tuple combining both ``visit_*`` and ``depart_*`` call back functions for a :class:`Landscape` node.""" diff --git a/sphinx_reports/LaTeX.py b/sphinx_reports/LaTeX.py index e69de29b..536971d5 100644 --- a/sphinx_reports/LaTeX.py +++ b/sphinx_reports/LaTeX.py @@ -0,0 +1,70 @@ +# ==================================================================================================================== # +# _ _ _ # +# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # +# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # +# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # +# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # +# |_| |_| # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2026-2026 Patrick Lehmann - Bötzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +from typing import Tuple + +from sphinx.writers.latex import LaTeXTranslator + +from pyTooling.Decorators import export +from sphinx_reports.Common import visitFunc, departFunc +from sphinx_reports.Node import Landscape + + +__all__ = ["translateLandscape"] + + +@export +def visit_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: + """ + Call back function for visiting a :class:`Landscape`. + + This function begins a ``landscape`` environment in LaTeX. + + :param translator: The LaTeX translator instance. + :param node: The current node being visited. + """ + translator.body.append(r'\begin{landscape}') + + +@export +def depart_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: + """ + Call back function for departing a :class:`Landscape`. + + This function ends a ``landscape`` environment in LaTeX. + + :param translator: The LaTeX translator instance. + :param node: The current node being departed. + """ + translator.body.append(r'\end{landscape}') + + +translateLandscape: Tuple[visitFunc, departFunc] = (visit_Landscape, depart_Landscape) +"""A tuple combining both ``visit_*`` and ``depart_*`` call back functions for a :class:`Landscape` node.""" diff --git a/sphinx_reports/Node.py b/sphinx_reports/Node.py index e69de29b..d53130b8 100644 --- a/sphinx_reports/Node.py +++ b/sphinx_reports/Node.py @@ -0,0 +1,40 @@ +# ==================================================================================================================== # +# _ _ _ # +# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # +# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # +# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # +# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # +# |_| |_| # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2026-2026 Patrick Lehmann - Bötzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +from docutils.nodes import container + +from pyTooling.Decorators import export + + +@export +class Landscape(container): + """ + A container node used in LaTeX to render content in landscape view in PDF pages. + """ diff --git a/sphinx_reports/Unittest.py b/sphinx_reports/Unittest.py index a9928109..d83b0100 100644 --- a/sphinx_reports/Unittest.py +++ b/sphinx_reports/Unittest.py @@ -45,6 +45,7 @@ from sphinx.config import Config from sphinx_reports.Common import ReportExtensionError +from sphinx_reports.Node import Landscape from sphinx_reports.Sphinx import strip, stripAndNormalize, BaseDirective @@ -54,12 +55,12 @@ class report_DictType(TypedDict): @export class ShowTestcases(Flag): - passed = 1 - failed = 2 - skipped = 4 - excluded = 8 - errors = 16 - aborted = 32 + passed = 1 + failed = 2 + skipped = 4 + excluded = 8 + errors = 16 + aborted = 32 all = passed | failed | skipped | excluded | errors | aborted not_passed = all & ~passed @@ -356,7 +357,7 @@ def renderSummary(self, tableBody: nodes.tbody, testsuiteSummary: TestsuiteSumma tableRow += nodes.entry("", nodes.Text(f"{self._formatTimedelta(testsuiteSummary.TotalDuration)}")) def run(self) -> List[nodes.Node]: - container = nodes.container() + container = Landscape() try: self._CheckOptions() diff --git a/sphinx_reports/__init__.py b/sphinx_reports/__init__.py index 993901e5..6843f5b2 100644 --- a/sphinx_reports/__init__.py +++ b/sphinx_reports/__init__.py @@ -43,7 +43,7 @@ __email__ = "Paebbels@gmail.com" __copyright__ = "2023-2026, Patrick Lehmann" __license__ = "Apache License, Version 2.0" -__version__ = "0.10.0" +__version__ = "0.11.0" __keywords__ = [ "Python3", "Sphinx", "Extension", "Report", "doc-string", "interrogate", "Code Coverage", "Coverage", "Documentation Coverage", "Unittest", "Dependencies", "Summary" @@ -51,9 +51,9 @@ from hashlib import md5 from pathlib import Path -from typing import TYPE_CHECKING, Any, Tuple, Dict, Optional as Nullable, TypedDict, List, Callable +from typing import TYPE_CHECKING, Any, Tuple, Dict, Optional as Nullable, TypedDict, List, Callable, Type -from docutils import nodes +from docutils.nodes import Element from sphinx.addnodes import pending_xref from sphinx.application import Sphinx from sphinx.builders import Builder @@ -65,7 +65,18 @@ from pyTooling.Common import readResourceFile from sphinx_reports import static as ResourcePackage -from sphinx_reports.Common import ReportExtensionError +from sphinx_reports.Common import ReportExtensionError, visitFunc, departFunc +from sphinx_reports.Node import Landscape +from sphinx_reports.HTML import translateLandscape as translateLandscapeAsHTML +from sphinx_reports.LaTeX import translateLandscape as translateLandscapeAsLaTeX + + +@export +class RegisteredNode(TypedDict): + name: str + node: Type[Element] + html: Tuple[visitFunc, departFunc] + latex: Tuple[visitFunc, departFunc] @export @@ -106,6 +117,17 @@ class ReportDomain(Domain): dependencies: List[str] = [ ] #: A list of other extensions this domain depends on. + latexPackages: Tuple[str, ...] = ( + "pdflscape", + ) + nodes: Tuple[RegisteredNode, ...] = ( + { "name": "Landscape", + "node": Landscape, + "html": translateLandscapeAsHTML, + "latex": translateLandscapeAsLaTeX + }, + ) + from sphinx_reports.CodeCoverage import CodeCoverage, CodeCoverageLegend, ModuleCoverage from sphinx_reports.DocCoverage import DocStrCoverage, DocCoverageLegend from sphinx_reports.Dependency import DependencyTable @@ -262,8 +284,8 @@ def resolve_xref( typ: str, target: str, node: pending_xref, - contnode: nodes.Element - ) -> Nullable[nodes.Element]: + contnode: Element + ) -> Nullable[Element]: raise NotImplementedError() @@ -291,6 +313,14 @@ def setup(sphinxApplication: Sphinx) -> "setup_ReturnType": """ sphinxApplication.add_domain(ReportDomain) + # Request new LaTeX package dependencies + for latexPackage in ReportDomain.latexPackages: + sphinxApplication.add_latex_package(latexPackage) + + # Register new docutil nodes. + for newNode in ReportDomain.nodes: + sphinxApplication.add_node(newNode["node"], html=newNode["html"], latex=newNode["latex"]) + # Register callbacks for eventName, callbacks in ReportDomain.callbacks.items(): for callback in callbacks: @@ -303,6 +333,6 @@ def setup(sphinxApplication: Sphinx) -> "setup_ReturnType": return { "version": __version__, # version of the extension "env_version": int(__version__.split(".")[0]), # version of the data structure stored in the environment - 'parallel_read_safe': False, # Not yet evaluated, thus false + 'parallel_read_safe': False, # TODO: Not yet evaluated, thus false 'parallel_write_safe': True, # Internal data structure is used read-only, thus no problems will occur by parallel writing. } From c55cb139facd98c8810e842fd8766361ec173ace Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 26 Apr 2026 22:05:22 +0200 Subject: [PATCH 3/8] Dropped Python 3.11 support due to Sphinx 9.1 dropping Python 3.11 support. --- .github/workflows/Pipeline.yml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/Pipeline.yml b/.github/workflows/Pipeline.yml index ea5b5e67..6d6c55d7 100644 --- a/.github/workflows/Pipeline.yml +++ b/.github/workflows/Pipeline.yml @@ -18,7 +18,7 @@ jobs: uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@r7 with: package_name: 'sphinx_reports' - unittest_python_version_list: '3.11 3.12 3.13 3.14' + unittest_python_version_list: '3.12 3.13 3.14' # dropped 3.11 due to Sphinx 9.1 dropping 3.11 unittest_disable_list: 'windows-arm:* windows-arm:pypy-3.11' bandit: 'true' pylint: 'false' diff --git a/setup.py b/setup.py index 1fc4c97c..aa003e51 100644 --- a/setup.py +++ b/setup.py @@ -55,7 +55,7 @@ "Topic :: Software Development :: Testing :: Unit", ], developmentStatus="beta", - pythonVersions=("3.11", "3.12", "3.13", "3.14"), + pythonVersions=("3.12", "3.13", "3.14"), # dropped 3.11 due to Sphinx 9.1 dropping 3.11. dataFiles={ "sphinx_reports": ["static/*.css"] }, From ba5ae20b99e8289bd7ef4547c854f169a881337f Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sun, 26 Apr 2026 23:04:03 +0200 Subject: [PATCH 4/8] Build LaTeX output and run LuaLaTeX for PDF generation. --- .github/workflows/Pipeline.yml | 1 + doc/CodeCov/index.rst | 16 ++-- doc/Dependency.rst | 29 ++++++-- doc/DocCov/index.rst | 16 ++-- doc/Unittest/index.rst | 16 ++-- doc/conf.py | 132 +++++++++++++++++---------------- doc/shields.inc | 2 +- doc/unittests/index.rst | 2 + sphinx_reports/__init__.py | 11 ++- 9 files changed, 126 insertions(+), 99 deletions(-) diff --git a/.github/workflows/Pipeline.yml b/.github/workflows/Pipeline.yml index 6d6c55d7..0d11beae 100644 --- a/.github/workflows/Pipeline.yml +++ b/.github/workflows/Pipeline.yml @@ -25,6 +25,7 @@ jobs: codecov: 'true' codacy: 'true' dorny: 'true' + documentation_steps: 'html latex pdf pages' secrets: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/doc/CodeCov/index.rst b/doc/CodeCov/index.rst index ca4845a6..05d48385 100644 --- a/doc/CodeCov/index.rst +++ b/doc/CodeCov/index.rst @@ -1,4 +1,4 @@ -.. _CODECOV: +.. _CODECOVER: Code Coverage ############# @@ -10,7 +10,7 @@ Code Coverage The :rst:dir:`report:code-coverage` directive generates a code coverage report summary table. The code coverage report file(s) need to be configured in Sphinx's ``conf.py`` for pre-analysis and data aggregation - (:ref:`see below ` for details). This also allows the directive to supports multiple code coverage + (:ref:`see below ` for details). This also allows the directive to supports multiple code coverage reports per Sphinx documentation. Each code coverage report is referenced by the :rst:dir:`reportid ` option, which matches the dictionary key used in the configuration file. @@ -62,7 +62,7 @@ Code Coverage .. image:: ../_static/CodeCoverage.png -.. _CODECOV/Config: +.. _CODECOVER/Config: Configuration Entries in :file:`conf.py` **************************************** @@ -134,7 +134,7 @@ Configuration Entries in :file:`conf.py` } -.. _CODECOV/Example: +.. _CODECOVER/Example: Example Document **************** @@ -197,7 +197,7 @@ The second file shows how to integrate that document into the navigation bar / * :hidden: -.. _CODECOV/Directives: +.. _CODECOVER/Directives: Sphinx Directives ***************** @@ -249,7 +249,7 @@ The following directives are provided for visualizing code coverage reports. -.. _CODECOV/Roles: +.. _CODECOVER/Roles: Sphinx Roles ************ @@ -257,7 +257,7 @@ Sphinx Roles *There are no roles defined.* -.. _CODECOV/ColorPalett: +.. _CODECOVER/ColorPalett: Color Paletts ************* @@ -289,7 +289,7 @@ Color Paletts :width: 350 px -.. _CODECOV/Styling: +.. _CODECOVER/Styling: Custom CSS Styling ****************** diff --git a/doc/Dependency.rst b/doc/Dependency.rst index 18edd486..d12d2239 100644 --- a/doc/Dependency.rst +++ b/doc/Dependency.rst @@ -3,14 +3,27 @@ Dependencies ############ -.. |img-pyTooling-lib-status| image:: https://img.shields.io/librariesio/release/pypi/sphinx-reports - :alt: Libraries.io status for latest release - :height: 22 - :target: https://libraries.io/github/pyTooling/sphinx-reports -.. |img-pyTooling-vul-status| image:: https://img.shields.io/snyk/vulnerabilities/github/pyTooling/sphinx-reports - :alt: Snyk Vulnerabilities for GitHub Repo - :height: 22 - :target: https://img.shields.io/snyk/vulnerabilities/github/pyTooling/sphinx-reports +.. only:: html + + .. |img-pyTooling-lib-status| image:: https://img.shields.io/librariesio/release/pypi/sphinx-reports + :alt: Libraries.io status for latest release + :height: 22 + :target: https://libraries.io/github/pyTooling/sphinx-reports + .. |img-pyTooling-vul-status| image:: https://img.shields.io/snyk/vulnerabilities/github/pyTooling/sphinx-reports + :alt: Snyk Vulnerabilities for GitHub Repo + :height: 22 + :target: https://raster.shields.io/snyk/vulnerabilities/github/pyTooling/sphinx-reports + +.. only:: latex + + .. |img-pyTooling-lib-status| image:: https://raster.shields.io/librariesio/release/pypi/sphinx-reports + :alt: Libraries.io status for latest release + :height: 22 + :target: https://libraries.io/github/pyTooling/sphinx-reports + .. |img-pyTooling-vul-status| image:: https://raster.shields.io/snyk/vulnerabilities/github/pyTooling/sphinx-reports + :alt: Snyk Vulnerabilities for GitHub Repo + :height: 22 + :target: https://raster.shields.io/snyk/vulnerabilities/github/pyTooling/sphinx-reports +------------------------------------------+------------------------------------------+ | `Libraries.io `_ | Vulnerabilities Summary | diff --git a/doc/DocCov/index.rst b/doc/DocCov/index.rst index e2788323..d9b4ba9a5 100644 --- a/doc/DocCov/index.rst +++ b/doc/DocCov/index.rst @@ -1,4 +1,4 @@ -.. _DOCCOV: +.. _DOCCOVER: Documentation Coverage ###################### @@ -10,7 +10,7 @@ Documentation Coverage The :rst:dir:`report:doc-coverage` directive generates a documentation coverage report summary table. The documentation coverage reports need to be configured in Sphinx's ``conf.py`` for pre-analysis and data aggregation - (:ref:`see below ` for details). This also allows the directive to supports multiple documentation + (:ref:`see below ` for details). This also allows the directive to supports multiple documentation coverage reports per Sphinx documentation. Each documentation coverage report is referenced by the :rst:dir:`reportid ` option, which matches the dictionary key used in the configuration file. @@ -55,7 +55,7 @@ Documentation Coverage .. image:: ../_static/DocCoverage.png -.. _DOCCOV/Config: +.. _DOCCOVER/Config: Configuration Entries in :file:`conf.py` **************************************** @@ -130,7 +130,7 @@ Configuration Entries in :file:`conf.py` } -.. _DOCCOV/Example: +.. _DOCCOVER/Example: Example Document **************** @@ -150,7 +150,7 @@ The second file shows how to integrate that document into the navigation bar / * .. code-block:: ReST - .. _DOCCOV: + .. _DOCCOVER: Documentation Coverage Report ############################# @@ -194,7 +194,7 @@ The second file shows how to integrate that document into the navigation bar / * :hidden: -.. _DOCCOV/Directives: +.. _DOCCOVER/Directives: Sphinx Directives ***************** @@ -241,7 +241,7 @@ The following directives are provided for visualizing documentation coverage rep * ``vertical-table`` -.. _DOCCOV/Roles: +.. _DOCCOVER/Roles: Sphinx Roles ************ @@ -249,7 +249,7 @@ Sphinx Roles *There are no roles defined.* -.. _DOCCOV/ColorPalett: +.. _DOCCOVER/ColorPalett: Color Paletts ************* diff --git a/doc/Unittest/index.rst b/doc/Unittest/index.rst index 0d1b541e..61de9d5e 100644 --- a/doc/Unittest/index.rst +++ b/doc/Unittest/index.rst @@ -1,4 +1,4 @@ -.. _UNITTEST: +.. _UNITTESTING: Unit Test Summary ################# @@ -10,7 +10,7 @@ Unit Test Summary The :rst:dir:`report:unittest-summary` directive generates a unittest report summary table. The unittest report file(s) need to be configured in Sphinx's ``conf.py`` for pre-analysis and data aggregation - (:ref:`see below ` for details). This also allows the directive to supports multiple unittest + (:ref:`see below ` for details). This also allows the directive to supports multiple unittest reports per Sphinx documentation. Each unittest report is referenced by the :rst:dir:`report ` option, which matches the dictionary key used in the configuration file. @@ -72,7 +72,7 @@ Unit Test Summary .. tab-item:: Only Testsuites - .. image:: ../_static/Unittest_OnlyTestsuites.png + .. #image:: ../_static/Unittest_OnlyTestsuites.png .. tab-item:: Testsuites and Testcases :selected: @@ -80,7 +80,7 @@ Unit Test Summary .. image:: ../_static/Unittest.png -.. _UNITTEST/Config: +.. _UNITTESTING/Config: Configuration Entries in :file:`conf.py` **************************************** @@ -120,7 +120,7 @@ Configuration Entries in :file:`conf.py` } -.. _UNITTEST/Example: +.. _UNITTESTING/Example: Example Document **************** @@ -171,7 +171,7 @@ The second file shows how to integrate that document into the navigation bar / * :hidden: -.. _UNITTEST/Directives: +.. _UNITTESTING/Directives: Sphinx Directives ***************** @@ -213,7 +213,7 @@ The following directives are provided for visualizing unittest reports. -.. _UNITTEST/Roles: +.. _UNITTESTING/Roles: Sphinx Roles ************ @@ -222,7 +222,7 @@ Sphinx Roles -.. _UNITTEST/Styling: +.. _UNITTESTING/Styling: Custom CSS Styling ****************** diff --git a/doc/conf.py b/doc/conf.py index dd2083ed..3baf5774 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,19 +1,29 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -from sys import path as sys_path -from os.path import abspath -from pathlib import Path -from json import loads +from sys import path as sys_path +from os.path import abspath +from pathlib import Path +from textwrap import dedent from pyTooling.Packaging import extractVersionInformation +# ============================================================================== +# Project configuration +# ============================================================================== +githubNamespace = "pyTooling" +githubProject = pythonProject = "sphinx_reports" +directoryName = pythonProject.replace('.', '/') + + +# ============================================================================== +# Project paths +# ============================================================================== ROOT = Path(__file__).resolve().parent sys_path.insert(0, abspath(".")) sys_path.insert(0, abspath("..")) -sys_path.insert(0, abspath("../sphinx_reports")) -# sys_path.insert(0, abspath("_extensions")) +sys_path.insert(0, abspath(f"../{directoryName}")) # ============================================================================== @@ -22,12 +32,10 @@ # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. -project = "sphinx_reports" -directoryName = project.replace('.', '/') - packageInformationFile = Path(f"../{directoryName}/__init__.py") versionInformation = extractVersionInformation(packageInformationFile) +project = pythonProject author = versionInformation.Author copyright = versionInformation.Copyright version = ".".join(versionInformation.Version.split(".")[:2]) # e.g. 2.3 The short X.Y version. @@ -70,14 +78,6 @@ rst_prolog = "" -# ============================================================================== -# Options for HTML output -# ============================================================================== -html_context = {} -ctx = ROOT / "context.json" -if ctx.is_file(): - html_context.update(loads(ctx.open("r", encoding="utf-8").read())) - # ============================================================================== # Options for HTML output # ============================================================================== @@ -96,11 +96,11 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] -html_logo = str(Path(html_static_path[0]) / "logo.png") -html_favicon = str(Path(html_static_path[0]) / "icon.png") +html_logo = str(Path(html_static_path[0]) / "logo.png") # logo.svg +html_favicon = str(Path(html_static_path[0]) / "icon.png") # favicon.png # Output file base name for HTML help builder. -htmlhelp_basename = "sphinx_reportsDoc" +htmlhelp_basename = f"{project}Doc" # If not None, a 'Last updated on:' timestamp is inserted at every page # bottom, using the given strftime format. @@ -111,52 +111,58 @@ # Python settings # ============================================================================== modindex_common_prefix = [ - f"{project}." + f"{pythonProject}." ] # ============================================================================== # Options for LaTeX / PDF output # ============================================================================== -from textwrap import dedent - +latex_engine = "lualatex" +latex_use_xindy = False latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - "papersize": "a4paper", - - # The font size ('10pt', '11pt' or '12pt'). - #'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - "preamble": dedent(r""" - % ================================================================================ - % User defined additional preamble code - % ================================================================================ - % Add more Unicode characters for pdfLaTeX. - % - Alternatively, compile with XeLaTeX or LuaLaTeX. - % - https://GitHub.com/sphinx-doc/sphinx/issues/3511 - % - \ifdefined\DeclareUnicodeCharacter - \DeclareUnicodeCharacter{2265}{$\geq$} - \DeclareUnicodeCharacter{21D2}{$\Rightarrow$} - \fi - - - % ================================================================================ - """), - - # Latex figure (float) alignment - #'figure_align': 'htbp', + "papersize": "a4paper", # The paper size ('letterpaper' or 'a4paper'). + "pointsize": "10pt", # The font size ('10pt', '11pt' or '12pt'). + "inputenc": "", # Let LuaLaTeX handle input encoding + "utf8extra": "", + "polyglossia": "", + "babel": r"\usepackage[english]{babel}", + "fontenc": r"\usepackage{fontspec}", # Disable the default T1 font encoding (Essential for LuaLaTeX) + "fontpkg": dedent("""\ + \\usepackage{unicode-math} + + % Set the Text Fonts (Libertinus) + \\setmainfont{Libertinus Serif} + \\setsansfont{Libertinus Sans} + \\setmonofont{Libertinus Mono} + \\setmathfont{Libertinus Math} + + % Set Symbol font + \\usepackage{newunicodechar} + \\newfontfamily{\\emojifont}[Renderer=OpenType]{NotoColorEmoji.ttf} + \\usepackage{pytooling} + \\newunicodechar{❓}{{\\emojifont ❓}} % Black Question Mark Ornament U+2753 + \\newunicodechar{❗}{{\\emojifont ❗}} % Heavy Exclamation Mark Symbol U+2757 + \\newunicodechar{➖}{{\\emojifont ➖}} % Heavy Minus Sign U+2796 + """), + "passoptionstopackages": dedent("""\ + \\PassOptionsToPackage{verbatimvisiblespace=\\ }{sphinx} + """), +# "sphinxsetup": "verbatimvisiblespace=\\textvisiblespace" +# "figure_align": "htbp", # Latex figure (float) alignment + "makeindex": r"\usepackage[columns=1]{idxlayout}\makeindex", + "printindex": r"\def\twocolumn[#1]{#1}\printindex", } + # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ( master_doc, - "sphinx_reports.tex", - "The sphinx_reports Documentation", - "Patrick Lehmann", - "manual" + f"{pythonProject}.tex", + f"The {pythonProject.replace("_", r"\_")} Documentation", + "Patrick Lehmann", + "manual" ), ] @@ -193,6 +199,7 @@ intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "pyTool": ("https://pyTooling.github.io/pyTooling/", None), + "edarpt": ("https://edaa.org.github.io/pyEDAA.Reports/", None), } @@ -216,11 +223,12 @@ # Sphinx.Ext.ExtLinks # ============================================================================== extlinks = { - "gh": ("https://GitHub.com/%s", "gh:%s"), - "ghissue": ("https://GitHub.com/pytooling/sphinx_reports/issues/%s", "issue #%s"), - "ghpull": ("https://GitHub.com/pytooling/sphinx_reports/pull/%s", "pull request #%s"), - "ghsrc": ("https://GitHub.com/pytooling/sphinx_reports/blob/main/%s", None), - "wiki": ("https://en.wikipedia.org/wiki/%s", None), + "gh": (f"https://GitHub.com/%s", "%s"), + "ghissue": (f"https://GitHub.com/{githubNamespace}/{githubProject}/issues/%s", "issue #%s"), + "ghpull": (f"https://GitHub.com/{githubNamespace}/{githubProject}/pull/%s", "pull request #%s"), + "ghsrc": (f"https://GitHub.com/{githubNamespace}/{githubProject}/blob/main/%s", None), + "pypi": ( "https://PyPI.org/project/%s", "%s"), + "wiki": (f"https://en.wikipedia.org/wiki/%s", None), } @@ -273,7 +281,7 @@ report_codecov_packages = { "src": { - "name": f"{project}", + "name": f"{pythonProject}", "json_report": "../report/coverage/coverage.json", "fail_below": 80, "levels": "default" @@ -282,7 +290,7 @@ report_doccov_packages = { "src": { - "name": f"{project}", + "name": f"{pythonProject}", "directory": f"../{directoryName}", "fail_below": 80, "levels": "default" @@ -318,9 +326,9 @@ # AutoAPI.Sphinx # ============================================================================== autoapi_modules = { - project: { + pythonProject: { "template": "module", - "output": project, + "output": pythonProject, "override": True } } diff --git a/doc/shields.inc b/doc/shields.inc index 8033740e..74cb116e 100644 --- a/doc/shields.inc +++ b/doc/shields.inc @@ -18,7 +18,7 @@ :alt: Code license :height: 22 :target: Code-License.html -.. |SHIELD:png:SphinxReports-src-license| image:: https://img.shields.io/pypi/l/sphinx-reports?longCache=true&style=flat-square&logo=Apache&label=code +.. |SHIELD:png:SphinxReports-src-license| image:: https://raster.shields.io/pypi/l/sphinx-reports?longCache=true&style=flat-square&logo=Apache&label=code :alt: Code license :height: 22 :target: https://GitHub.com/pyTooling/sphinx-reports/blob/main/LICENSE.md diff --git a/doc/unittests/index.rst b/doc/unittests/index.rst index 32022017..a9556763 100644 --- a/doc/unittests/index.rst +++ b/doc/unittests/index.rst @@ -1,3 +1,5 @@ +.. _UNITTEST: + Unittest Summary Report ####################### diff --git a/sphinx_reports/__init__.py b/sphinx_reports/__init__.py index 6843f5b2..dfa01b04 100644 --- a/sphinx_reports/__init__.py +++ b/sphinx_reports/__init__.py @@ -73,10 +73,13 @@ @export class RegisteredNode(TypedDict): - name: str - node: Type[Element] - html: Tuple[visitFunc, departFunc] - latex: Tuple[visitFunc, departFunc] + """ + Type information for an entry in :attr:`ReportDomain.nodes`. + """ + name: str #: Name of the new docutils node to register. + node: Type[Element] #: The new node class to register. + html: Tuple[visitFunc, departFunc] #: A tuple of visit and depart functions rendering the new node in case of HTML output. + latex: Tuple[visitFunc, departFunc] #: A tuple of visit and depart functions rendering the new node in case of LaTeX output. @export From 061e86f6ad20615f830c7cde696e54de73864b5c Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Thu, 14 May 2026 19:53:08 +0200 Subject: [PATCH 5/8] Rerun with latest MiKTeX image and new Unicode symbols in pytooling.sty. --- doc/conf.py | 4 ---- sphinx_reports/LaTeX.py | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 3baf5774..5d0ce196 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -140,9 +140,6 @@ \\usepackage{newunicodechar} \\newfontfamily{\\emojifont}[Renderer=OpenType]{NotoColorEmoji.ttf} \\usepackage{pytooling} - \\newunicodechar{❓}{{\\emojifont ❓}} % Black Question Mark Ornament U+2753 - \\newunicodechar{❗}{{\\emojifont ❗}} % Heavy Exclamation Mark Symbol U+2757 - \\newunicodechar{➖}{{\\emojifont ➖}} % Heavy Minus Sign U+2796 """), "passoptionstopackages": dedent("""\ \\PassOptionsToPackage{verbatimvisiblespace=\\ }{sphinx} @@ -153,7 +150,6 @@ "printindex": r"\def\twocolumn[#1]{#1}\printindex", } - # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). diff --git a/sphinx_reports/LaTeX.py b/sphinx_reports/LaTeX.py index 536971d5..0c6d214f 100644 --- a/sphinx_reports/LaTeX.py +++ b/sphinx_reports/LaTeX.py @@ -28,6 +28,7 @@ # SPDX-License-Identifier: Apache-2.0 # # ==================================================================================================================== # # +from textwrap import dedent from typing import Tuple from sphinx.writers.latex import LaTeXTranslator @@ -50,8 +51,14 @@ def visit_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: :param translator: The LaTeX translator instance. :param node: The current node being visited. """ - translator.body.append(r'\begin{landscape}') - + translator.body.append(dedent("""\ + \\begin{landscape} + \\begingroup + \\setlength{\\textwidth}{\\textheight} + \\setlength{\\linewidth}{\\textwidth} + \\setlength{\\hsize}{\\textwidth} + """) + ) @export def depart_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: @@ -63,7 +70,11 @@ def depart_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: :param translator: The LaTeX translator instance. :param node: The current node being departed. """ - translator.body.append(r'\end{landscape}') + translator.body.append(dedent("""\ + \\endgroup + \\end{landscape} + """) + ) translateLandscape: Tuple[visitFunc, departFunc] = (visit_Landscape, depart_Landscape) From 966cd71d1248dde8dd3a59cf1d851d7afdbf53e6 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 15 May 2026 01:07:13 +0200 Subject: [PATCH 6/8] Changed colwidth from 100 to 1. --- doc/conf.py | 7 ++++--- sphinx_reports/CodeCoverage.py | 20 ++++++++++---------- sphinx_reports/Dependency.py | 8 ++++---- sphinx_reports/DocCoverage.py | 24 ++++++++++++------------ sphinx_reports/LaTeX.py | 9 ++------- sphinx_reports/Unittest.py | 20 ++++++++++---------- 6 files changed, 42 insertions(+), 46 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 5d0ce196..097ebcbe 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -122,7 +122,7 @@ latex_elements = { "papersize": "a4paper", # The paper size ('letterpaper' or 'a4paper'). "pointsize": "10pt", # The font size ('10pt', '11pt' or '12pt'). - "inputenc": "", # Let LuaLaTeX handle input encoding + "inputenc": "", # Let LuaLaTeX handle input encoding "utf8extra": "", "polyglossia": "", "babel": r"\usepackage[english]{babel}", @@ -138,7 +138,8 @@ % Set Symbol font \\usepackage{newunicodechar} - \\newfontfamily{\\emojifont}[Renderer=OpenType]{NotoColorEmoji.ttf} + \\newfontfamily{\\emojifont}[Renderer=OpenType, Scale=0.6]{NotoColorEmoji.ttf} + \\newcommand{\\emoji}[1]{{\\raisebox{0.1em}{\\emojifont{#1}}}} \\usepackage{pytooling} """), "passoptionstopackages": dedent("""\ @@ -195,7 +196,7 @@ intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "pyTool": ("https://pyTooling.github.io/pyTooling/", None), - "edarpt": ("https://edaa.org.github.io/pyEDAA.Reports/", None), + "edarpt": ("https://edaa-org.github.io/pyEDAA.Reports/", None), } diff --git a/sphinx_reports/CodeCoverage.py b/sphinx_reports/CodeCoverage.py index 6b35399f..d22e7598 100644 --- a/sphinx_reports/CodeCoverage.py +++ b/sphinx_reports/CodeCoverage.py @@ -301,10 +301,10 @@ def _GenerateCoverageTable(self) -> nodes.table: # Create a table and table header with 10 columns columns = [ - ("Package", [(" Module", 500)], None), - ("Statments", [("Total", 100), ("Excluded", 100), ("Covered", 100), ("Missing", 100), ("Coverage", 100)], None), - ("Branches" , [("Total", 100), ("Covered", 100), ("Partial", 100), ("Missing", 100), ("Coverage", 100)], None), - # ("Coverage", [("in %", 100)], None) + ("Package", [(" Module", 5)], None), + ("Statments", [("Total", 1), ("Excluded", 1), ("Covered", 1), ("Missing", 1), ("Coverage", 1)], None), + ("Branches" , [("Total", 1), ("Covered", 1), ("Partial", 1), ("Missing", 1), ("Coverage", 1)], None), + # ("Coverage", [("in %", 1)], None) ] if self._noBranchCoverage: @@ -517,12 +517,12 @@ def _CheckOptions(self) -> None: self._levels = packageConfiguration["levels"] def _CreateHorizontalLegendTable(self, identifier: str, classes: List[str]) -> nodes.table: - columns = [("Code Coverage:", None, 300)] + columns = [("Code Coverage:", 3)] for level in self._levels: if isinstance(level, int): - columns.append((f"≤{level} %", None, 200)) + columns.append((f"≤{level} %", 2)) - tableGroup = self._CreateDoubleRowTableHeader(columns, identifier=identifier, classes=classes) + tableGroup = self._CreateSingleTableHeader(columns, identifier=identifier, classes=classes) tableBody = nodes.tbody() tableGroup += tableBody @@ -543,9 +543,9 @@ def _CreateHorizontalLegendTable(self, identifier: str, classes: List[str]) -> n return table def _CreateVerticalLegendTable(self, identifier: str, classes: List[str]) -> nodes.table: - tableGroup = self._CreateDoubleRowTableHeader([ - ("Code Coverage", None, 300), - ("Coverage Level", None, 300) + tableGroup = self._CreateSingleTableHeader([ + ("Code Coverage", 3), + ("Coverage Level", 3) ], identifier=identifier, classes=classes diff --git a/sphinx_reports/Dependency.py b/sphinx_reports/Dependency.py index 542e66ed..da9a01c9 100644 --- a/sphinx_reports/Dependency.py +++ b/sphinx_reports/Dependency.py @@ -86,12 +86,12 @@ def CheckConfiguration(cls, sphinxApplication: Sphinx, sphinxConfiguration: Conf def _GenerateDependencyTable(self) -> nodes.table: # Create a table and table header with 8 columns columns = [ - ("Package", None, 500), - ("Version", None, 100), - ("License", None, 100), + ("Package", 5), + ("Version", 1), + ("License", 1), ] - tableGroup = self._CreateDoubleRowTableHeader( + tableGroup = self._CreateSingleTableHeader( identifier=self._packageName, columns=columns, classes=["report-dependency-table"] diff --git a/sphinx_reports/DocCoverage.py b/sphinx_reports/DocCoverage.py index f9c9b31d..a481fe51 100644 --- a/sphinx_reports/DocCoverage.py +++ b/sphinx_reports/DocCoverage.py @@ -271,14 +271,14 @@ def _GenerateCoverageTable(self) -> nodes.table: cssClasses.extend(self._cssClasses) # Create a table and table header with 5 columns - tableGroup = self._CreateDoubleRowTableHeader( + tableGroup = self._CreateSingleTableHeader( identifier=self._reportID, columns=[ - ("Filename", None, 500), - ("Total", None, 100), - ("Covered", None, 100), - ("Missing", None, 100), - ("Coverage in %", None, 100) + ("Filename", 5), + ("Total", 1), + ("Covered", 1), + ("Missing", 1), + ("Coverage in %", 1) ], classes=cssClasses ) @@ -391,12 +391,12 @@ def _CheckOptions(self) -> None: self._levels = packageConfiguration["levels"] def _CreateHorizontalLegendTable(self, identifier: str, classes: List[str]) -> nodes.table: - columns = [("Documentation Coverage:", None, 300)] + columns = [("Documentation Coverage:", 3)] for level in self._levels: if isinstance(level, int): - columns.append((f"≤{level} %", None, 200)) + columns.append((f"≤{level} %", 2)) - tableGroup = self._CreateDoubleRowTableHeader(columns, identifier=identifier, classes=classes) + tableGroup = self._CreateSingleTableHeader(columns, identifier=identifier, classes=classes) tableBody = nodes.tbody() tableGroup += tableBody @@ -410,9 +410,9 @@ def _CreateHorizontalLegendTable(self, identifier: str, classes: List[str]) -> n return table def _CreateVerticalLegendTable(self, identifier: str, classes: List[str]) -> nodes.table: - tableGroup = self._CreateDoubleRowTableHeader([ - ("Documentation Coverage", None, 300), - ("Coverage Level", None, 300) + tableGroup = self._CreateSingleTableHeader([ + ("Documentation Coverage", 3), + ("Coverage Level", 3) ], identifier=identifier, classes=classes diff --git a/sphinx_reports/LaTeX.py b/sphinx_reports/LaTeX.py index 0c6d214f..619635e6 100644 --- a/sphinx_reports/LaTeX.py +++ b/sphinx_reports/LaTeX.py @@ -51,12 +51,8 @@ def visit_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: :param translator: The LaTeX translator instance. :param node: The current node being visited. """ - translator.body.append(dedent("""\ + translator.body.append(dedent(""" \\begin{landscape} - \\begingroup - \\setlength{\\textwidth}{\\textheight} - \\setlength{\\linewidth}{\\textwidth} - \\setlength{\\hsize}{\\textwidth} """) ) @@ -70,8 +66,7 @@ def depart_Landscape(translator: LaTeXTranslator, node: Landscape) -> None: :param translator: The LaTeX translator instance. :param node: The current node being departed. """ - translator.body.append(dedent("""\ - \\endgroup + translator.body.append(dedent(""" \\end{landscape} """) ) diff --git a/sphinx_reports/Unittest.py b/sphinx_reports/Unittest.py index d83b0100..4db6d9d1 100644 --- a/sphinx_reports/Unittest.py +++ b/sphinx_reports/Unittest.py @@ -247,24 +247,24 @@ def _formatTimedelta(self, delta: timedelta) -> str: def _GenerateTestSummaryTable(self) -> nodes.table: # Create a table and table header with 8 columns columns = [ - ("Testsuite / Testcase", None, 500), - ("Testcases", None, 100), - ("Skipped", None, 100), - ("Errored", None, 100), - ("Failed", None, 100), - ("Passed", None, 100), - ("Assertions", None, 100), - ("Runtime (HH:MM:SS.sss)", None, 100), + ("Testsuite / Testcase", 5), + ("Testcases", 1), + ("Skipped", 1), + ("Errored", 1), + ("Failed", 1), + ("Passed", 1), + ("Assertions", 1), + ("Runtime (HH:MM:SS.sss)", 1), ] # If assertions shouldn't be displayed, remove column from columns list if self._noAssertions: columns.pop(6) - cssClasses = ["report-unittest-table", f"report-unittest-{self._reportID}"] + cssClasses = ["colwidths-given", "report-unittest-table", f"report-unittest-{self._reportID}"] cssClasses.extend(self._cssClasses) - tableGroup = self._CreateDoubleRowTableHeader( + tableGroup = self._CreateSingleTableHeader( identifier=self._reportID, columns=columns, classes=cssClasses From 4638d83cc1dbc540336a659df8ee95daaef9a51c Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Fri, 15 May 2026 15:31:14 +0200 Subject: [PATCH 7/8] Added a transformation to apply the workaround. --- doc/conf.py | 14 +-------- sphinx_reports/Unittest.py | 2 +- sphinx_reports/Workaround.py | 58 ++++++++++++++++++++++++++++++++++++ sphinx_reports/__init__.py | 21 +++++++++---- 4 files changed, 75 insertions(+), 20 deletions(-) create mode 100644 sphinx_reports/Workaround.py diff --git a/doc/conf.py b/doc/conf.py index 097ebcbe..1dc30e5d 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -128,19 +128,7 @@ "babel": r"\usepackage[english]{babel}", "fontenc": r"\usepackage{fontspec}", # Disable the default T1 font encoding (Essential for LuaLaTeX) "fontpkg": dedent("""\ - \\usepackage{unicode-math} - - % Set the Text Fonts (Libertinus) - \\setmainfont{Libertinus Serif} - \\setsansfont{Libertinus Sans} - \\setmonofont{Libertinus Mono} - \\setmathfont{Libertinus Math} - - % Set Symbol font - \\usepackage{newunicodechar} - \\newfontfamily{\\emojifont}[Renderer=OpenType, Scale=0.6]{NotoColorEmoji.ttf} - \\newcommand{\\emoji}[1]{{\\raisebox{0.1em}{\\emojifont{#1}}}} - \\usepackage{pytooling} + \\usepackage[fontfamily=libertinus]{pytooling} """), "passoptionstopackages": dedent("""\ \\PassOptionsToPackage{verbatimvisiblespace=\\ }{sphinx} diff --git a/sphinx_reports/Unittest.py b/sphinx_reports/Unittest.py index 4db6d9d1..d9583327 100644 --- a/sphinx_reports/Unittest.py +++ b/sphinx_reports/Unittest.py @@ -261,7 +261,7 @@ def _GenerateTestSummaryTable(self) -> nodes.table: if self._noAssertions: columns.pop(6) - cssClasses = ["colwidths-given", "report-unittest-table", f"report-unittest-{self._reportID}"] + cssClasses = ["report-unittest-table", f"report-unittest-{self._reportID}"] cssClasses.extend(self._cssClasses) tableGroup = self._CreateSingleTableHeader( diff --git a/sphinx_reports/Workaround.py b/sphinx_reports/Workaround.py new file mode 100644 index 00000000..4c50a137 --- /dev/null +++ b/sphinx_reports/Workaround.py @@ -0,0 +1,58 @@ +# ==================================================================================================================== # +# _ _ _ # +# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # +# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # +# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # +# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # +# |_| |_| # +# ==================================================================================================================== # +# Authors: # +# Patrick Lehmann # +# # +# License: # +# ==================================================================================================================== # +# Copyright 2023-2026 Patrick Lehmann - Bötzingen, Germany # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +# SPDX-License-Identifier: Apache-2.0 # +# ==================================================================================================================== # +# +""" +Workarounds for Sphinx and Docutils problems. +""" +from docutils.nodes import table +from docutils.transforms import Transform +from sphinx.util.logging import getLogger + +logger = getLogger(__name__) + +class FixLatexTableWidths(Transform): + default_priority = 500 + + def apply(self): + sphinxEnvironment = self.document.settings.env + + if sphinxEnvironment.app.builder.format != "latex": + return + + # search for all table nodes + for tableNode in self.document.findall(table): + if (cssClasses := tableNode.get("classes", None)) is None: + continue + + if "report-unittest-table" in cssClasses: + if 'colwidths-given' not in cssClasses: + cssClasses.append('colwidths-given') + + logger.info("Applied 'colwidths-given' to a table via FixLatexTableWidths transform.", location=tableNode) diff --git a/sphinx_reports/__init__.py b/sphinx_reports/__init__.py index dfa01b04..384b8da8 100644 --- a/sphinx_reports/__init__.py +++ b/sphinx_reports/__init__.py @@ -54,6 +54,7 @@ from typing import TYPE_CHECKING, Any, Tuple, Dict, Optional as Nullable, TypedDict, List, Callable, Type from docutils.nodes import Element +from docutils.transforms import Transform from sphinx.addnodes import pending_xref from sphinx.application import Sphinx from sphinx.builders import Builder @@ -64,11 +65,12 @@ from pyTooling.Decorators import export from pyTooling.Common import readResourceFile -from sphinx_reports import static as ResourcePackage -from sphinx_reports.Common import ReportExtensionError, visitFunc, departFunc -from sphinx_reports.Node import Landscape -from sphinx_reports.HTML import translateLandscape as translateLandscapeAsHTML -from sphinx_reports.LaTeX import translateLandscape as translateLandscapeAsLaTeX +from sphinx_reports import static as ResourcePackage +from sphinx_reports.Common import ReportExtensionError, visitFunc, departFunc +from sphinx_reports.Node import Landscape +from sphinx_reports.Workaround import FixLatexTableWidths +from sphinx_reports.HTML import translateLandscape as translateLandscapeAsHTML +from sphinx_reports.LaTeX import translateLandscape as translateLandscapeAsLaTeX @export @@ -130,6 +132,9 @@ class ReportDomain(Domain): "latex": translateLandscapeAsLaTeX }, ) + transformations: Tuple[Type[Transform], ...] = ( + FixLatexTableWidths, + ) from sphinx_reports.CodeCoverage import CodeCoverage, CodeCoverageLegend, ModuleCoverage from sphinx_reports.DocCoverage import DocStrCoverage, DocCoverageLegend @@ -324,6 +329,10 @@ def setup(sphinxApplication: Sphinx) -> "setup_ReturnType": for newNode in ReportDomain.nodes: sphinxApplication.add_node(newNode["node"], html=newNode["html"], latex=newNode["latex"]) + # Register transformations + for transformation in ReportDomain.transformations: + sphinxApplication.add_post_transform(transformation) + # Register callbacks for eventName, callbacks in ReportDomain.callbacks.items(): for callback in callbacks: @@ -336,6 +345,6 @@ def setup(sphinxApplication: Sphinx) -> "setup_ReturnType": return { "version": __version__, # version of the extension "env_version": int(__version__.split(".")[0]), # version of the data structure stored in the environment - 'parallel_read_safe': False, # TODO: Not yet evaluated, thus false + 'parallel_read_safe': True, # TODO: Not yet evaluated 'parallel_write_safe': True, # Internal data structure is used read-only, thus no problems will occur by parallel writing. } From 2b86090ec25f6693c7aecb2332624741b6ba6c08 Mon Sep 17 00:00:00 2001 From: Patrick Lehmann Date: Sat, 16 May 2026 00:32:03 +0200 Subject: [PATCH 8/8] Reworked document structure. --- README.md | 1 - doc/Doc-License.rst | 89 ++++++++++++++++++++----- doc/License.rst | 116 +++++++++++++++++++++++++++------ doc/index.rst | 27 +++----- sphinx_reports/CodeCoverage.py | 3 +- sphinx_reports/Unittest.py | 4 +- sphinx_reports/Workaround.py | 7 +- 7 files changed, 185 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index f175bf14..0302aaf9 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,6 @@ The accompanying documentation is licensed under Creative Commons - Attribution- ------------------------- - SPDX-License-Identifier: Apache-2.0 diff --git a/doc/Doc-License.rst b/doc/Doc-License.rst index ca0c2560..e7bc9466 100644 --- a/doc/Doc-License.rst +++ b/doc/Doc-License.rst @@ -1,12 +1,17 @@ .. _DOCLICENSE: +.. raw:: latex + + \chapter{Creative Commons Attribution 4.0 International} + .. note:: This is a local copy of the `Creative Commons - Attribution 4.0 International (CC BY 4.0) `__. .. attention:: This **CC BY 4.0** license applies only to the **documentation** of this project. +.. only:: html -Creative Commons Attribution 4.0 International -############################################## + Creative Commons Attribution 4.0 International + ############################################## Creative Commons Corporation (“Creative Commons”) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public @@ -61,8 +66,14 @@ Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. -Section 1 – Definitions. -======================== +.. raw:: latex + + \section{Section 1 – Definitions.} + +.. only:: html + + Section 1 – Definitions. + ======================== a. **Adapted Material** means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in @@ -120,8 +131,14 @@ j. **Sui Generis Database Rights** means rights other than copyright k. **You** means the individual or entity exercising the Licensed Rights under this Public License. **Your** has a corresponding meaning. -Section 2 – Scope. -================== +.. raw:: latex + + \section{Section 2 – Scope.} + +.. only:: html + + Section 2 – Scope. + ================== a. **License grant.** @@ -186,8 +203,14 @@ b. **Other rights.** compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. -Section 3 – License Conditions. -=============================== +.. raw:: latex + + \section{Section 3 – License Conditions.} + +.. only:: html + + Section 3 – License Conditions. + =============================== Your exercise of the Licensed Rights is expressly made subject to the following conditions. @@ -231,8 +254,14 @@ a. **Attribution.** must not prevent recipients of the Adapted Material from complying with this Public License. -Section 4 – Sui Generis Database Rights. -======================================== +.. raw:: latex + + \section{Section 4 – Sui Generis Database Rights.} + +.. only:: html + + Section 4 – Sui Generis Database Rights. + ======================================== Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: @@ -253,8 +282,14 @@ For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. -Section 5 – Disclaimer of Warranties and Limitation of Liability. -================================================================= +.. raw:: latex + + \section{Section 5 – Disclaimer of Warranties and Limitation of Liability.} + +.. only:: html + + Section 5 – Disclaimer of Warranties and Limitation of Liability. + ================================================================= a. **Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, @@ -279,8 +314,14 @@ c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. -Section 6 – Term and Termination. -================================= +.. raw:: latex + + \section{Section 6 – Term and Termination.} + +.. only:: html + + Section 6 – Term and Termination. + ================================= a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then @@ -303,8 +344,14 @@ c. For the avoidance of doubt, the Licensor may also offer the Licensed Material d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. -Section 7 – Other Terms and Conditions. -======================================= +.. raw:: latex + + \section{Section 7 – Other Terms and Conditions.} + +.. only:: html + + Section 7 – Other Terms and Conditions. + ======================================= a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. @@ -313,8 +360,14 @@ b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. -Section 8 – Interpretation. -=========================== +.. raw:: latex + + \section{Section 8 – Interpretation.} + +.. only:: html + + Section 8 – Interpretation. + =========================== a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of diff --git a/doc/License.rst b/doc/License.rst index 7df6024f..62452d32 100644 --- a/doc/License.rst +++ b/doc/License.rst @@ -1,15 +1,33 @@ -.. Note:: This is a local copy of the `Apache License Version 2.0 `_. +.. _CODELICENSE: -Apache License 2.0 -################## +.. raw:: latex + + \chapter{Apache License 2.0} + +.. note:: + + This is a local copy of the `Apache License Version 2.0 `_. + + SPDX-License-Identifier: Apache-2.0 + +.. only:: html + + Apache License 2.0 + ################## Version 2.0, January 2004 **TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION** +.. raw:: latex + + \section{1. Definitions.} + +.. only:: html + + 1. Definitions. + =============== -1. Definitions. -=============== **"License"** shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. **"Licensor"** shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. @@ -43,14 +61,28 @@ conspicuously marked or otherwise designated in writing by the copyright owner a **"Contributor"** shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. -2. Grant of Copyright License. -============================== +.. raw:: latex + + \section{2. Grant of Copyright License.} + +.. only:: html + + 2. Grant of Copyright License. + ============================== + Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. -3. Grant of Patent License. -=========================== +.. raw:: latex + + \section{3. Grant of Patent License.} + +.. only:: html + + 3. Grant of Patent License. + =========================== + Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of @@ -58,8 +90,15 @@ their Contribution(s) with the Work to which such Contribution(s) was submitted. or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. -4. Redistribution. -================== +.. raw:: latex + + \section{4. Redistribution.} + +.. only:: html + + 4. Redistribution. + ================== + You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: @@ -78,34 +117,69 @@ You may add Your own copyright statement to Your modifications and may provide a distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. -5. Submission of Contributions. -=============================== +.. raw:: latex + + \section{5. Submission of Contributions.} + +.. only:: html + + 5. Submission of Contributions. + =============================== + Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. -6. Trademarks. -============== +.. raw:: latex + + \section{6. Trademarks.} + +.. only:: html + + 6. Trademarks. + ============== + This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. -7. Disclaimer of Warranty. -========================== +.. raw:: latex + + \section{7. Disclaimer of Warranty.} + +.. only:: html + + 7. Disclaimer of Warranty. + ========================== + Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. -8. Limitation of Liability. -=========================== +.. raw:: latex + + \section{8. Limitation of Liability.} + +.. only:: html + + 8. Limitation of Liability. + =========================== + In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. -9. Accepting Warranty or Additional Liability. -============================================== +.. raw:: latex + + \section{9. Accepting Warranty or Additional Liability.} + +.. only:: html + + 9. Accepting Warranty or Additional Liability. + ============================================== + While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability diff --git a/doc/index.rst b/doc/index.rst index 2c0f6ec7..34a50e87 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -34,18 +34,18 @@ Supported Report Formats Supported format reports are: -* ✅🚧 :ref:`Unit Test summaries ` (by `pytest `__) +* ✅🚧 :ref:`Unit Test summaries ` (by `pytest `__) * ✅ Summary page (displaying ``unittest.xml``) * 🚧 Show logging, output and error messages. -* 🚧 :ref:`Code coverage ` (by `Coverage.py `__) +* 🚧 :ref:`Code coverage ` (by `Coverage.py `__) * ✅ Summary page (displaying ``coverage.json``) * 🚧 Individual Sphinx documents per package/module * 🚧 Highlighted source code with syntax highlighting and coverage highlighting -* 🚧 :ref:`Documentation coverage ` +* 🚧 :ref:`Documentation coverage ` * ✅ Summary page (displaying data from `"""docstr_coverage""" `__) * ❓ Additionally support `interrogate `__ as data source. @@ -65,7 +65,7 @@ Unit Test Summary .. grid-item:: :columns: 6 - :ref:`Unittesting ` executes isolated tests on tiny source code portions (units). The results are + :ref:`Unittesting ` executes isolated tests on tiny source code portions (units). The results are collected in a unittest summary report usually in the Any JUnit XML format (or a related dialect). These test results can be visualized as a hierarchy of groups (testsuites) and tests (testcases). @@ -103,7 +103,7 @@ Code Coverage .. grid-item:: :columns: 6 - :ref:`CODECOV` checks if a source code (lines, statements, branches, ...) were used during execution. Usually, + :ref:`CODECOVER` checks if a source code (lines, statements, branches, ...) were used during execution. Usually, testcases are run by a testcase execution framework like `pytest `__, which also offers to instrument the source code for code coverage collection using the ``pytest-cov`` plugin. For Python, code coverage collection is usually based on `Coverage.py `__, which @@ -141,9 +141,9 @@ Documentation coverage .. grid-item:: :columns: 6 - :ref:`DOCCOV` counts how many publicly accessible members are documented using a Python :term:`doc-string`. Based - on the count of possibly documented public members and the actual number of non-empty *doc-strings*, a percentage - of documentation coverage can be computed. + :ref:`DOCCOVER` counts how many publicly accessible members are documented using a Python :term:`doc-string`. + Based on the count of possibly documented public members and the actual number of non-empty *doc-strings*, a + percentage of documentation coverage can be computed. .. rubric:: Configuration Options @@ -187,15 +187,8 @@ Contributors License ******* -.. only:: html - - This Python package (source code) is licensed under `Apache License 2.0 `__. |br| - The accompanying documentation is licensed under `Creative Commons - Attribution 4.0 (CC-BY 4.0) `__. - -.. only:: latex - - This Python package (source code) is licensed under **Apache License 2.0**. |br| - The accompanying documentation is licensed under **Creative Commons - Attribution 4.0 (CC-BY 4.0)**. +This Python package (source code) is licensed under :ref:`Apache License 2.0 `. |br| +The accompanying documentation is licensed under :ref:`Creative Commons - Attribution 4.0 (CC-BY 4.0) `. .. toctree:: diff --git a/sphinx_reports/CodeCoverage.py b/sphinx_reports/CodeCoverage.py index d22e7598..1ff2f686 100644 --- a/sphinx_reports/CodeCoverage.py +++ b/sphinx_reports/CodeCoverage.py @@ -45,6 +45,7 @@ from sphinx_reports.Common import ReportExtensionError, LegendStyle from sphinx_reports.Sphinx import strip, stripAndNormalize, BaseDirective +from sphinx_reports.Node import Landscape from sphinx_reports.DataModel.CodeCoverage import PackageCoverage, Coverage, ModuleCoverage from sphinx_reports.Adapter.Coverage import Analyzer @@ -419,7 +420,7 @@ def handleModule(module: ModuleCoverage) -> None: handlePackage(self._coverage) def run(self) -> List[nodes.Node]: - container = nodes.container() + container = Landscape() try: self._CheckOptions() diff --git a/sphinx_reports/Unittest.py b/sphinx_reports/Unittest.py index d9583327..9c2ba3b7 100644 --- a/sphinx_reports/Unittest.py +++ b/sphinx_reports/Unittest.py @@ -247,14 +247,14 @@ def _formatTimedelta(self, delta: timedelta) -> str: def _GenerateTestSummaryTable(self) -> nodes.table: # Create a table and table header with 8 columns columns = [ - ("Testsuite / Testcase", 5), + ("Testsuite / Testcase", 6), ("Testcases", 1), ("Skipped", 1), ("Errored", 1), ("Failed", 1), ("Passed", 1), ("Assertions", 1), - ("Runtime (HH:MM:SS.sss)", 1), + ("Runtime (HH:MM:SS.sss)", 2), ] # If assertions shouldn't be displayed, remove column from columns list diff --git a/sphinx_reports/Workaround.py b/sphinx_reports/Workaround.py index 4c50a137..19d0440e 100644 --- a/sphinx_reports/Workaround.py +++ b/sphinx_reports/Workaround.py @@ -46,13 +46,16 @@ def apply(self): if sphinxEnvironment.app.builder.format != "latex": return + # Tables used with Landscape node + tableClasses = ("report-unittest-table", "report-codecov-table") + # search for all table nodes for tableNode in self.document.findall(table): if (cssClasses := tableNode.get("classes", None)) is None: continue - if "report-unittest-table" in cssClasses: + if any(tableClass in cssClasses for tableClass in tableClasses): if 'colwidths-given' not in cssClasses: cssClasses.append('colwidths-given') - + logger.info("Applied 'colwidths-given' to a table via FixLatexTableWidths transform.", location=tableNode)