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..0d11beae 100644 --- a/.github/workflows/Pipeline.yml +++ b/.github/workflows/Pipeline.yml @@ -7,18 +7,25 @@ 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 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' 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/README.md b/README.md index dbcc72ad..0302aaf9 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) @@ -218,7 +218,6 @@ The accompanying documentation is licensed under Creative Commons - Attribution- ------------------------- - SPDX-License-Identifier: Apache-2.0 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/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 5e477e6b..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 | @@ -104,7 +117,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 +167,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 +175,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/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/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/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/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/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 268341eb..1dc30e5d 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,41 +111,32 @@ # 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[fontfamily=libertinus]{pytooling} + """), + "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 @@ -153,10 +144,10 @@ # 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 +184,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 +208,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), } @@ -233,6 +226,8 @@ # ============================================================================== # SphinxContrib.Mermaid # ============================================================================== +mermaid_cmd = "mmdc" +mermaid_cmd_shell = True mermaid_params = [ '--backgroundColor', 'transparent', ] @@ -271,7 +266,7 @@ report_codecov_packages = { "src": { - "name": f"{project}", + "name": f"{pythonProject}", "json_report": "../report/coverage/coverage.json", "fail_below": 80, "levels": "default" @@ -280,7 +275,7 @@ report_doccov_packages = { "src": { - "name": f"{project}", + "name": f"{pythonProject}", "directory": f"../{directoryName}", "fail_below": 80, "levels": "default" @@ -316,9 +311,9 @@ # AutoAPI.Sphinx # ============================================================================== autoapi_modules = { - project: { + pythonProject: { "template": "module", - "output": project, + "output": pythonProject, "override": True } } 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/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/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/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/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"] }, diff --git a/sphinx_reports/CodeCoverage.py b/sphinx_reports/CodeCoverage.py index 6b35399f..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 @@ -301,10 +302,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: @@ -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() @@ -517,12 +518,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 +544,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/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/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/HTML.py b/sphinx_reports/HTML.py new file mode 100644 index 00000000..44efc776 --- /dev/null +++ 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 new file mode 100644 index 00000000..619635e6 --- /dev/null +++ b/sphinx_reports/LaTeX.py @@ -0,0 +1,76 @@ +# ==================================================================================================================== # +# _ _ _ # +# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # +# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # +# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # +# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # +# |_| |_| # +# ==================================================================================================================== # +# 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 textwrap import dedent +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(dedent(""" + \\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(dedent(""" + \\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 new file mode 100644 index 00000000..d53130b8 --- /dev/null +++ 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..9c2ba3b7 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 @@ -246,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", 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", 6), + ("Testcases", 1), + ("Skipped", 1), + ("Errored", 1), + ("Failed", 1), + ("Passed", 1), + ("Assertions", 1), + ("Runtime (HH:MM:SS.sss)", 2), ] # If assertions shouldn't be displayed, remove column from columns list @@ -263,7 +264,7 @@ def _GenerateTestSummaryTable(self) -> nodes.table: cssClasses = ["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 @@ -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/Workaround.py b/sphinx_reports/Workaround.py new file mode 100644 index 00000000..19d0440e --- /dev/null +++ b/sphinx_reports/Workaround.py @@ -0,0 +1,61 @@ +# ==================================================================================================================== # +# _ _ _ # +# ___ _ __ | |__ (_)_ __ __ __ _ __ ___ _ __ ___ _ __| |_ ___ # +# / __| '_ \| '_ \| | '_ \\ \/ /____| '__/ _ \ '_ \ / _ \| '__| __/ __| # +# \__ \ |_) | | | | | | | |> <_____| | | __/ |_) | (_) | | | |_\__ \ # +# |___/ .__/|_| |_|_|_| |_/_/\_\ |_| \___| .__/ \___/|_| \__|___/ # +# |_| |_| # +# ==================================================================================================================== # +# 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 + + # 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 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) diff --git a/sphinx_reports/__init__.py b/sphinx_reports/__init__.py index 993901e5..384b8da8 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,10 @@ 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 docutils.transforms import Transform from sphinx.addnodes import pending_xref from sphinx.application import Sphinx from sphinx.builders import Builder @@ -64,8 +65,23 @@ from pyTooling.Decorators import export from pyTooling.Common import readResourceFile -from sphinx_reports import static as ResourcePackage -from sphinx_reports.Common import ReportExtensionError +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 +class RegisteredNode(TypedDict): + """ + 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 @@ -106,6 +122,20 @@ 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 + }, + ) + transformations: Tuple[Type[Transform], ...] = ( + FixLatexTableWidths, + ) + from sphinx_reports.CodeCoverage import CodeCoverage, CodeCoverageLegend, ModuleCoverage from sphinx_reports.DocCoverage import DocStrCoverage, DocCoverageLegend from sphinx_reports.Dependency import DependencyTable @@ -262,8 +292,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 +321,18 @@ 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 transformations + for transformation in ReportDomain.transformations: + sphinxApplication.add_post_transform(transformation) + # Register callbacks for eventName, callbacks in ReportDomain.callbacks.items(): for callback in callbacks: @@ -303,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, # 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. } 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