Merged Code Coverage and Python 3.12

This commit is contained in:
Patrick Lehmann
2024-01-13 13:25:55 +01:00
committed by GitHub
45 changed files with 1372 additions and 364 deletions

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -85,7 +85,7 @@ jobs:
uses: actions/checkout@v4
- name: 📥 Download artifacts '${{ inputs.wheel }}' from 'Package' job
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ inputs.wheel }}
path: install
@@ -180,7 +180,7 @@ jobs:
- name: 🐍 Setup Python ${{ matrix.python }}
if: matrix.system != 'msys2'
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
@@ -222,7 +222,7 @@ jobs:
- name: 📤 Upload 'TestReportSummary.xml' artifact
if: inputs.artifact != ''
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact }}-${{ matrix.system }}-${{ matrix.python }}
path: ${{ inputs.tests_directory || '.' }}/TestReportSummary.xml

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -45,12 +45,14 @@ jobs:
- name: 🗑️ Delete package Artifacts
if: ${{ ! startsWith(github.ref, 'refs/tags') }}
uses: geekyeggo/delete-artifact@v2
uses: geekyeggo/delete-artifact@v4
with:
name: ${{ inputs.package }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: 🗑️ Delete remaining Artifacts
if: ${{ inputs.remaining != '' }}
uses: geekyeggo/delete-artifact@v2
uses: geekyeggo/delete-artifact@v4
with:
name: ${{ inputs.remaining }}
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -47,7 +47,7 @@ jobs:
- name: 📤 Upload 'documentation' artifacts
if: inputs.artifact != ''
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact }}
path: doc/_build/html

View File

@@ -0,0 +1,67 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# 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 #
# ==================================================================================================================== #
name: Check Documentation
on:
workflow_call:
inputs:
python_version:
description: 'Python version.'
required: false
default: '3.12'
type: string
directory:
description: 'Source code directory to check.'
required: true
type: string
# fail_below:
# description: 'Minimum required documentation coverage level'
# required: false
# default: 75
# type: string
jobs:
DocCoverage:
name: 👀 Check documentation coverage
runs-on: ubuntu-latest
steps:
- name: ⏬ Checkout repository
uses: actions/checkout@v4
- name: 🐍 Setup Python 3.11
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: 🔧 Install wheel,tomli and pip dependencies (native)
run: |
python -m pip install --disable-pip-version-check -U docstr_coverage interrogate
- name: Run 'interrogate' Documentation Coverage Check
continue-on-error: true
run: |
interrogate -c pyproject.toml
- name: Run 'docstr_coverage' Documentation Coverage Check
continue-on-error: true
run: |
docstr_coverage -v ${{ inputs.directory }}

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -70,7 +70,7 @@ jobs:
uses: actions/checkout@v4
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
@@ -148,7 +148,7 @@ jobs:
- name: 📤 Upload 'Coverage Report' artifact
continue-on-error: true
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_html_directory }}

View File

@@ -1,17 +1,9 @@
# ==================================================================================================================== #
# _____ _ _ _ _ _ #
# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / \ ___| |_(_) ___ _ __ ___ #
# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` | / _ \ / __| __| |/ _ \| '_ \/ __| #
# | |_) | |_| || | (_) | (_) | | | | | | (_| |_ / ___ \ (__| |_| | (_) | | | \__ \ #
# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)_/ \_\___|\__|_|\___/|_| |_|___/ #
# |_| |___/ |___/ #
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Bötzingen, Germany #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -27,11 +19,37 @@
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""Placeholder"""
__author__ = "Patrick Lehmann"
__email__ = "Paebbels@gmail.com"
__copyright__ = "2017-2022, Patrick Lehmann"
__license__ = "Apache License, Version 2.0"
__version__ = "0.4.4"
__keywords__ = []
name: Intermediate Cleanup
on:
workflow_call:
inputs:
sqlite_coverage_artifacts_prefix:
description: 'Prefix for SQLite coverage artifacts'
required: false
type: string
xml_unittest_artifacts_prefix:
description: 'Prefix for XML unittest artifacts'
required: false
type: string
jobs:
IntermediateCleanUp:
name: 🗑️ Intermediate Artifact Cleanup
runs-on: ubuntu-latest
steps:
- name: 🗑️ Delete SQLite coverage artifacts from matrix jobs
uses: geekyeggo/delete-artifact@v4
if: inputs.sqlite_coverage_artifacts_prefix != ''
continue-on-error: true
with:
name: ${{ inputs.sqlite_coverage_artifacts_prefix }}*
token: ${{ secrets.GITHUB_TOKEN }}
- name: 🗑️ Delete XML coverage artifacts from matrix jobs
uses: geekyeggo/delete-artifact@v4
if: inputs.xml_unittest_artifacts_prefix != ''
continue-on-error: true
with:
name: ${{ inputs.xml_unittest_artifacts_prefix }}*
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,66 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# 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 #
# ==================================================================================================================== #
name: LaTeX Documentation
on:
workflow_call:
inputs:
document:
description: 'LaTeX root document without *.tex extension.'
required: true
type: string
latex_artifact:
description: 'Name of the LaTeX documentation artifact.'
required: false
default: ''
type: string
pdf_artifact:
description: 'Name of the PDF documentation artifact.'
required: false
default: ''
type: string
jobs:
PDFDocumentation:
name: 📓 Converting LaTeX Documentation to PDF
runs-on: ubuntu-latest
steps:
- name: 📥 Download artifacts '${{ inputs.latex_artifact }}' from 'SphinxDocumentation' job
uses: actions/download-artifact@v4
with:
name: ${{ inputs.latex_artifact }}
path: latex
- name: Compile LaTeX document
uses: xu-cheng/latex-action@master
with:
working_directory: latex
root_file: ${{ inputs.document }}.tex
- name: 📤 Upload 'PDF Documentation' artifact
uses: actions/upload-artifact@v4
if: inputs.pdf_artifact != ''
with:
name: ${{ inputs.pdf_artifact }}
path: ${{ inputs.document }}.pdf
if-no-files-found: error
retention-days: 1

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -28,7 +28,7 @@ on:
python_version:
description: 'Python version.'
required: false
default: '3.11'
default: '3.12'
type: string
requirements:
description: 'Python dependencies to be installed through pip; if empty, use pyproject.toml through build.'
@@ -51,7 +51,7 @@ jobs:
uses: actions/checkout@v4
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
@@ -98,7 +98,7 @@ jobs:
run: python setup.py bdist_wheel
- name: 📤 Upload wheel artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact }}
path: dist/

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -32,17 +32,17 @@ on:
python_version:
description: 'Python version.'
required: false
default: '3.11'
default: '3.12'
type: string
python_version_list:
description: 'Space separated list of Python versions to run tests with.'
required: false
default: '3.8 3.9 3.10 3.11'
default: '3.8 3.9 3.10 3.11 3.12'
type: string
system_list:
description: 'Space separated list of systems to run tests on.'
required: false
default: 'ubuntu windows mingw64 macos'
default: 'ubuntu windows macos mingw64 ucrt64'
type: string
include_list:
description: 'Space separated list of system:python items to be included into the list of test.'
@@ -102,9 +102,9 @@ jobs:
exclude_list = "${{ inputs.exclude_list }}".strip()
disable_list = "${{ inputs.disable_list }}".strip()
currentMSYS2Version = "3.10"
currentAlphaVersion = "3.12"
currentAlphaRelease = "3.12.0-alpha.1"
currentMSYS2Version = "3.11"
currentAlphaVersion = "3.13"
currentAlphaRelease = "3.13.0-alpha.1"
if systems == "":
print("::error title=Parameter::system_list is empty.")
@@ -131,8 +131,8 @@ jobs:
else:
disabled = [disable.strip() for disable in disable_list.split(" ")]
if "3.6" in versions:
print("::warning title=Deprecated::Support for Python 3.6 ended in 2021.12.23.")
if "3.7" in versions:
print("::warning title=Deprecated::Support for Python 3.7 ended in 2023.06.27.")
if "msys2" in systems:
print("::warning title=Deprecated::System 'msys2' will be replaced by 'mingw64'.")
if currentAlphaVersion in versions:
@@ -143,16 +143,17 @@ jobs:
data = {
# Python and PyPy versions supported by "setup-python" action
"python": {
"3.6": { "icon": "⚫", "until": "2021.12.23" },
"3.7": { "icon": "⚫", "until": "2023.06.27" },
"3.8": { "icon": "🔴", "until": "2024.10" },
"3.9": { "icon": "🟠", "until": "2025.10" },
"3.10": { "icon": "🟡", "until": "2026.10" },
"3.11": { "icon": "🟢", "until": "2027.10" },
"3.12": { "icon": "🟣", "until": "2028.10" },
"pypy-3.7": { "icon": "⟲🔴", "until": "????.??" },
"pypy-3.8": { "icon": "⟲🟠", "until": "????.??" },
"pypy-3.9": { "icon": "⟲🟡", "until": "????.??" },
"3.12": { "icon": "🟢", "until": "2028.10" },
# "3.13": { "icon": "🟣", "until": "2028.10" },
"pypy-3.7": { "icon": "⟲", "until": "????.??" },
"pypy-3.8": { "icon": "⟲🔴", "until": "????.??" },
"pypy-3.9": { "icon": "⟲🟠", "until": "????.??" },
"pypy-3.10": { "icon": "⟲🟡", "until": "????.??" },
},
# Runner systems (runner images) supported by GitHub Actions
"sys": {
@@ -211,6 +212,7 @@ jobs:
"sysicon": data["sys"][system]["icon"],
"system": system,
"runs-on": data["sys"][system]["runs-on"],
"runtime": "native",
"shell": data["sys"][system]["shell"],
"pyicon": data["python"][version]["icon"],
"python": currentAlphaRelease if version == currentAlphaVersion else version,
@@ -233,15 +235,19 @@ jobs:
artifact_names = {
"unittesting_xml": f"{name}-UnitTestReportSummary-XML",
"unittesting_html": f"{name}-UnitTestReportSummary-HTML",
"perftesting_xml": f"{name}-PerformanceTestReportSummary-XML",
"benchtesting_xml": f"{name}-BenchmarkTestReportSummary-XML",
"apptesting_xml": f"{name}-ApplicationTestReportSummary-XML",
"codecoverage_sqlite": f"{name}-CodeCoverage-SQLite",
"codecoverage_xml": f"{name}-CodeCoverage-XML",
"codecoverage_json": f"{name}-CodeCoverage-JSON",
"codecoverage_html": f"{name}-CodeCoverage-HTML",
"statictyping_html": f"{name}-StaticTyping-HTML",
"package_all": f"{name}-Packages",
"documentation_pdf": f"{name}-Documentation-PDF",
"documentation_html": f"{name}-Documentation-HTML",
"documentation_latex": f"{name}-Documentation-LaTeX",
"documentation_pdf": f"{name}-Documentation-PDF",
}
# Deprecated structure

View File

@@ -1,10 +0,0 @@
#name: Pipeline
name: Documentation
on:
push:
workflow_dispatch:
jobs:
BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@dev

View File

@@ -3,7 +3,7 @@
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -19,15 +19,35 @@
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
name: Publish Unit Test Results
name: Publish Code Coverage Results
on:
workflow_call:
inputs:
report_files:
description: 'Pattern of report files to upload. Can be a comma separated list.'
coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false
default: 'artifacts/**/*.xml'
default: 'pyproject.toml'
type: string
coverage_sqlite_artifact:
description: 'Name of the SQLite coverage artifact.'
required: false
default: ''
type: string
coverage_xml_artifact:
description: 'Name of the XML coverage artifact.'
required: false
default: ''
type: string
coverage_json_artifact:
description: 'Name of the JSON coverage artifact.'
required: false
default: ''
type: string
coverage_html_artifact:
description: 'Name of the HTML coverage artifact.'
required: false
default: ''
type: string
secrets:
codacy_token:
@@ -35,8 +55,8 @@ on:
required: true
jobs:
PublishTestResults:
name: 📊 Publish Test Results
PublishCoverageResults:
name: 📊 Publish Code Coverage Results
runs-on: ubuntu-latest
if: always()
@@ -45,10 +65,137 @@ jobs:
uses: actions/checkout@v4
- name: Download Artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
path: artifacts
- name: 🔧 Install coverage and tomli
run: |
python -m pip install --disable-pip-version-check -U coverage[toml] tomli
- name: 🔁 Extract configurations from pyproject.toml
id: getVariables
shell: python
run: |
from os import getenv
from pathlib import Path
from sys import version
from textwrap import dedent
print(f"Python: {version}")
from tomli import load as tomli_load
htmlDirectory = Path("htmlcov")
xmlFile = Path("./coverage.xml")
jsonFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file
if coverageRC == "pyproject.toml":
pyProjectFile = Path("pyproject.toml")
if pyProjectFile.exists():
with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else:
print(f"File '{pyProjectFile}' not found and no '.coveragerc' file specified.")
# Read output paths from '.coveragerc' file
elif len(coverageRC) > 0:
coverageRCFile = Path(coverageRC)
if coverageRCFile.exists():
with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"])
else:
print(f"File '{coverageRCFile}' not found.")
# Write jobs to special file
github_output = Path(getenv("GITHUB_OUTPUT"))
print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+", encoding="utf-8") as f:
f.write(dedent(f"""\
coverage_report_html_directory={htmlDirectory.as_posix()}
coverage_report_xml={xmlFile}
coverage_report_json={jsonFile}
"""))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
- name: Rename .coverage files and collect them all to coverage/
run: |
mkdir -p coverage
find . -type f -path "*artifacts*SQLite*.coverage" -exec sh -c 'cp -v $0 "coverage/$(basename $0).$(basename $(dirname $0))"' {} ';'
tree -a coverage
- name: Combine SQLite files (using Coverage.py)
run: coverage combine --data-file=.coverage coverage/
- name: Report code coverage
run: coverage report --rcfile=pyproject.toml --data-file=.coverage
- name: Convert to XML format (Cobertura)
if: inputs.coverage_xml_artifact != ''
run: coverage xml --data-file=.coverage
- name: Convert to JSON format
if: inputs.coverage_json_artifact != ''
run: coverage json --data-file=.coverage
- name: Convert to HTML format
if: inputs.coverage_html_artifact != ''
run: |
coverage html --data-file=.coverage -d report/coverage/html
rm report/coverage/html/.gitignore
tree -a report/coverage/html
- name: 📤 Upload 'Coverage SQLite Database' artifact
if: inputs.coverage_sqlite_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_sqlite_artifact }}
path: .coverage
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'Coverage XML Report' artifact
if: inputs.coverage_xml_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_xml_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_xml }}
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'Coverage JSON Report' artifact
if: inputs.coverage_json_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_json_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_json }}
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'Coverage HTML Report' artifact
if: inputs.coverage_html_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_html_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
if-no-files-found: error
retention-days: 1
- name: 📊 Publish code coverage at CodeCov
if: inputs.CodeCov == true
continue-on-error: true

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -28,7 +28,7 @@ on:
python_version:
description: 'Python version.'
required: false
default: '3.11'
default: '3.12'
type: string
requirements:
description: 'Python dependencies to be installed through pip.'
@@ -52,13 +52,13 @@ jobs:
steps:
- name: 📥 Download artifacts '${{ inputs.artifact }}' from 'Package' job
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ inputs.artifact }}
path: dist/
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
@@ -78,6 +78,6 @@ jobs:
run: twine upload dist/*.whl
- name: 🗑️ Delete packaging Artifacts
uses: geekyeggo/delete-artifact@v2
uses: geekyeggo/delete-artifact@v4
with:
name: ${{ inputs.artifact }}

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -25,10 +25,10 @@ name: Publish Unit Test Results
on:
workflow_call:
inputs:
report_files:
description: 'Pattern of report files to upload. Can be a comma separated list.'
merged_junit_artifact:
description: 'Name of the merged JUnit Test Summary artifact.'
required: false
default: 'artifacts/**/*.xml'
default: ''
type: string
jobs:
@@ -42,13 +42,48 @@ jobs:
uses: actions/checkout@v4
- name: Download Artifacts
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
path: artifacts
- name: 🔧 Install junitparser
run: |
python -m pip install --disable-pip-version-check -U junitparser
- name: Move JUnit files and collect them all to junit/
run: |
mkdir -p junit
find . -type f -path "*artifacts*UnitTestReportSummary*.xml" -exec sh -c 'cp -v $0 "junit/$(basename $(dirname $0)).$(basename $0)"' {} ';'
tree -a junit
- name: 🔁 Merge JUnit Unit Test Summaries
shell: python
run: |
from pathlib import Path
from junitparser import JUnitXml
junitDirectory = Path("junit")
junitXml = None
for file in junitDirectory.iterdir():
if junitXml is None:
junitXml = JUnitXml.fromfile(file)
else:
junitXml += JUnitXml.fromfile(file)
junitXml.write(junitDirectory / "merged.xml")
- name: 📊 Publish Unit Test Results
uses: dorny/test-reporter@v1
with:
name: Unit Test Results
path: ${{ inputs.report_files }}
path: junit/merged.xml
reporter: java-junit
- name: 📤 Upload merged 'JUnit Test Summary' artifact
if: inputs.merged_junit_artifact != ''
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.merged_junit_artifact }}
path: junit/merged.xml
if-no-files-found: error
retention-days: 1

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -51,21 +51,21 @@ jobs:
uses: actions/checkout@v4
- name: 📥 Download artifacts '${{ inputs.doc }}' from 'BuildTheDocs' job
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ inputs.doc }}
path: public
- name: 📥 Download artifacts '${{ inputs.coverage }}' from 'Coverage' job
if: ${{ inputs.coverage != '' }}
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ inputs.coverage }}
path: public/coverage
- name: 📥 Download artifacts '${{ inputs.typing }}' from 'StaticTypeCheck' job
if: ${{ inputs.typing != '' }}
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ inputs.typing }}
path: public/typing

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #

View File

@@ -0,0 +1,203 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# 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 #
# ==================================================================================================================== #
name: Documentation
on:
workflow_call:
inputs:
python_version:
description: 'Python version.'
required: false
default: '3.12'
type: string
requirements:
description: 'Python dependencies to be installed through pip.'
required: false
default: '-r doc/requirements.txt'
type: string
coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false
default: 'pyproject.toml'
type: string
doc_directory:
description: 'Path to the directory containing documentation (Sphinx working directory).'
required: false
default: 'doc'
type: string
coverage_json_artifact:
description: 'Name of the coverage JSON artifact.'
required: false
default: ''
type: string
unittest_xml_artifact:
description: 'Name of the unittest XML artifact.'
required: false
default: ''
type: string
unittest_xml_directory:
description: 'Directory where unittest XML artifact is extracted.'
required: false
default: 'report/unit'
type: string
html_artifact:
description: 'Name of the HTML documentation artifact.'
required: false
default: ''
type: string
latex_artifact:
description: 'Name of the LaTeX documentation artifact.'
required: false
default: ''
type: string
jobs:
Sphinx:
name: 📓 Documentation generation using Sphinx and Python ${{ inputs.python_version }}
runs-on: ubuntu-latest
steps:
- name: ⏬ Checkout repository
uses: actions/checkout@v4
- name: 🔧 Install graphviz
run: sudo apt-get install -y --no-install-recommends graphviz
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
- name: 🔧 Install wheel,tomli and pip dependencies (native)
run: |
python -m pip install --disable-pip-version-check -U wheel tomli
python -m pip install --disable-pip-version-check ${{ inputs.requirements }}
- name: 🔁 Extract configurations from pyproject.toml
id: getVariables
shell: python
run: |
from os import getenv
from pathlib import Path
from sys import version
from textwrap import dedent
print(f"Python: {version}")
from tomli import load as tomli_load
htmlDirectory = Path("htmlcov")
xmlFile = Path("./coverage.xml")
jsonFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file
if coverageRC == "pyproject.toml":
pyProjectFile = Path("pyproject.toml")
if pyProjectFile.exists():
with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else:
print(f"File '{pyProjectFile}' not found and no '.coveragerc' file specified.")
# Read output paths from '.coveragerc' file
elif len(coverageRC) > 0:
coverageRCFile = Path(coverageRC)
if coverageRCFile.exists():
with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"])
else:
print(f"File '{coverageRCFile}' not found.")
# Write jobs to special file
github_output = Path(getenv("GITHUB_OUTPUT"))
print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+", encoding="utf-8") as f:
f.write(dedent(f"""\
coverage_report_html_directory={htmlDirectory.as_posix()}
coverage_report_xml_directory={xmlFile.parent.as_posix()}
coverage_report_xml={xmlFile.as_posix()}
coverage_report_json_directory={jsonFile.parent.as_posix()}
coverage_report_json={jsonFile.as_posix()}
"""))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
- name: 📥 Download artifacts '${{ inputs.unittest_xml_artifact }}' from 'Unittesting' job
if: inputs.unittest_xml_artifact != ''
uses: actions/download-artifact@v4
with:
name: ${{ inputs.unittest_xml_artifact }}
path: ${{ inputs.unittest_xml_directory }}
- name: 📥 Download artifacts '${{ inputs.coverage_json_artifact }}' from 'PublishCoverageResults' job
if: inputs.coverage_json_artifact != ''
uses: actions/download-artifact@v4
with:
name: ${{ inputs.coverage_json_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_json_directory }}
- name: ☑ Generate HTML documentation
if: inputs.html_artifact != ''
run: |
export PYTHONPATH=$(pwd)
cd "${{ inputs.doc_directory || '.' }}"
sphinx-build -v -n -b html -d _build/doctrees -j $(nproc) -w _build/html.log . _build/html
- name: ☑ Generate LaTeX documentation
if: inputs.latex_artifact != ''
# continue-on-error: true
run: |
export PYTHONPATH=$(pwd)
cd "${{ inputs.doc_directory || '.' }}"
sphinx-build -v -n -b latex -d _build/doctrees -j $(nproc) -w _build/latex.log . _build/latex
# --builder html --doctree-dir _build/doctrees --verbose --fresh-env --write-all --nitpicky --warning-file _build/html.log . _build/html
- name: 📤 Upload 'HTML Documentation' artifact
if: inputs.html_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.html_artifact }}
path: ${{ inputs.doc_directory }}/_build/html
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'LaTeX Documentation' artifact
if: inputs.latex_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.latex_artifact }}
path: ${{ inputs.doc_directory }}/_build/latex
if-no-files-found: error
retention-days: 1

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -28,7 +28,7 @@ on:
python_version:
description: 'Python version.'
required: false
default: '3.11'
default: '3.12'
type: string
requirements:
description: 'Python dependencies to be installed through pip.'
@@ -70,7 +70,7 @@ jobs:
uses: actions/checkout@v4
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
@@ -84,7 +84,7 @@ jobs:
- name: 📤 Upload 'Static Typing Report' HTML artifact
if: ${{ inputs.html_artifact != '' }}
continue-on-error: true
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.html_artifact }}
path: ${{ inputs.html_report }}
@@ -94,7 +94,7 @@ jobs:
- name: 📤 Upload 'Static Typing Report' JUnit artifact
if: ${{ inputs.junit_artifact != '' }}
continue-on-error: true
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.junit_artifact }}
path: ${{ inputs.junit_report }}

View File

@@ -3,7 +3,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -20,7 +20,7 @@
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
name: Unit Testing
name: Unit Testing (Matrix)
on:
workflow_call:
@@ -54,16 +54,45 @@ on:
required: false
default: 'unit'
type: string
artifact:
coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false
default: 'pyproject.toml'
type: string
unittest_xml_artifact:
description: "Generate unit test report with junitxml and upload results as an artifact."
required: false
default: ''
type: string
unittest_html_artifact:
description: "Generate unit test report with junitxml and upload results as an artifact."
required: false
default: ''
type: string
coverage_sqlite_artifact:
description: 'Name of the SQLite coverage artifact.'
required: false
default: ''
type: string
coverage_xml_artifact:
description: 'Name of the XML coverage artifact.'
required: false
default: ''
type: string
coverage_json_artifact:
description: 'Name of the JSON coverage artifact.'
required: false
default: ''
type: string
coverage_html_artifact:
description: 'Name of the HTML coverage artifact.'
required: false
default: ''
type: string
jobs:
UnitTesting:
name: ${{ matrix.sysicon }} ${{ matrix.pyicon }} Unit Tests using Python ${{ matrix.python }}
name: ${{ matrix.sysicon }} ${{ matrix.pyicon }} Unit Tests - Python ${{ matrix.python }}
runs-on: ${{ matrix.runs-on }}
strategy:
@@ -79,6 +108,12 @@ jobs:
- name: ⏬ Checkout repository
uses: actions/checkout@v4
- name: 🔧 Install dependencies (system Python for Python shell)
if: matrix.system == 'msys2'
shell: pwsh
run: |
py -3.9 -m pip install --disable-pip-version-check -U tomli
- name: Compute pacman/pacboy packages
id: pacboy
if: matrix.system == 'msys2'
@@ -87,6 +122,9 @@ jobs:
from os import getenv
from pathlib import Path
from re import compile
from sys import version
print(f"Python: {version}")
def loadRequirementsFile(requirementsFile: Path):
requirements = []
@@ -111,28 +149,32 @@ jobs:
dependencies = [req.strip() for req in requirements.split(" ")]
packages = {
"pip": "python-pip:p",
"wheel": "python-wheel:p",
"coverage": "python-coverage:p",
"lxml": "python-lxml:p",
"ruamel.yaml": "python-ruamel-yaml:p python-ruamel.yaml.clib:p",
"numpy": "python-numpy:p",
"igraph": "igraph:p",
"jinja2": "python-markupsafe:p",
"lxml": "python-lxml:p",
"numpy": "python-numpy:p",
"markupsafe": "python-markupsafe:p",
"pip": "python-pip:p",
"ruamel.yaml": "python-ruamel-yaml:p python-ruamel.yaml.clib:p",
"sphinx": "python-markupsafe:p",
"tomli": "python-tomli:p",
"wheel": "python-wheel:p",
}
subPackages = {
"pyTooling": {
"pytooling": {
"yaml": "python-ruamel-yaml:p python-ruamel.yaml.clib:p",
}
}
regExp = compile(r"(?P<PackageName>[\w_\-\.]+)(?:\[(?P<SubPackages>(?:\w+)(?:,\w+)*)\])?(?:\s*(?P<Comperator>[<>=]+)\s*)(?P<Version>\d+(?:\.\d+)*)(?:-(?P<VersionExtension>\w+))?")
regExp = compile(r"(?P<PackageName>[\w_\-\.]+)(?:\[(?P<SubPackages>(?:\w+)(?:\s*,\s*\w+)*)\])?(?:\s*(?P<Comperator>[<>~=]+)\s*)(?P<Version>\d+(?:\.\d+)*)(?:-(?P<VersionExtension>\w+))?")
pacboyPackages = set(("python-pip:p", "python-wheel:p"))
pacboyPackages = set(("python-pip:p", "python-wheel:p", "python-tomli:p"))
print(f"Processing dependencies ({len(dependencies)}):")
for dependency in dependencies:
print(f" {dependency}")
match = regExp.match(dependency)
match = regExp.match(dependency.lower())
if not match:
print(f" Wrong format: {dependency}")
print(f"::error title=Identifying Pacboy Packages::Unrecognized dependency format '{dependency}'")
@@ -169,14 +211,14 @@ jobs:
- name: 🐍 Setup Python ${{ matrix.python }}
if: matrix.system != 'msys2'
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: 🔧 Install wheel and pip dependencies (native)
- name: 🔧 Install wheel,tomli and pip dependencies (native)
if: matrix.system != 'msys2'
run: |
python -m pip install --disable-pip-version-check -U wheel
python -m pip install --disable-pip-version-check -U wheel tomli
python -m pip install --disable-pip-version-check ${{ inputs.requirements }}
- name: 🔧 Install pip dependencies (MSYS2)
@@ -188,33 +230,164 @@ jobs:
python -m pip install --disable-pip-version-check ${{ inputs.requirements }}
fi
- name: ☑ Run unit tests (Windows)
if: matrix.system == 'windows'
- name: 🔁 Extract configurations from pyproject.toml
id: getVariables
shell: python
run: |
$env:ENVIRONMENT_NAME = "${{ matrix.envname }}"
$env:PYTHONPATH = (Get-Location).ToString()
cd "${{ inputs.tests_directory || '.' }}"
$PYTEST_ARGS = if ("${{ inputs.artifact }}") { "--junitxml=TestReportSummary.xml" } else { "" }
Write-Host "python -m pytest -rA $PYTEST_ARGS --color=yes ${{ inputs.unittest_directory }}"
python -m pytest -rA $PYTEST_ARGS --color=yes ${{ inputs.unittest_directory }}
from os import getenv
from pathlib import Path
from sys import version
from textwrap import dedent
print(f"Python: {version}")
from tomli import load as tomli_load
htmlDirectory = Path("htmlcov")
xmlFile = Path("./coverage.xml")
jsonFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file
if coverageRC == "pyproject.toml":
pyProjectFile = Path("pyproject.toml")
if pyProjectFile.exists():
with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else:
print(f"File '{pyProjectFile}' not found and no '.coveragerc' file specified.")
# Read output paths from '.coveragerc' file
elif len(coverageRC) > 0:
coverageRCFile = Path(coverageRC)
if coverageRCFile.exists():
with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"])
else:
print(f"File '{coverageRCFile}' not found.")
# Write jobs to special file
github_output = Path(getenv("GITHUB_OUTPUT"))
print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+", encoding="utf-8") as f:
f.write(dedent(f"""\
unittest_report_html_directory={htmlDirectory}
coverage_report_html_directory={htmlDirectory.as_posix()}
coverage_report_xml={xmlFile}
coverage_report_json={jsonFile}
"""))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
- name: ☑ Run unit tests (Ubuntu/macOS)
if: matrix.system != 'windows'
run: |
export ENVIRONMENT_NAME="${{ matrix.envname }}"
export PYTHONPATH=$(pwd)
ABSDIR=$(pwd)
cd "${{ inputs.tests_directory || '.' }}"
[ -n '${{ inputs.coverage_config }}' ] && PYCOV_ARGS="--cov-config=${ABSDIR}/${{ inputs.coverage_config }}" || unset PYCOV_ARGS
[ -n '${{ inputs.artifact }}' ] && PYTEST_ARGS='--junitxml=TestReportSummary.xml' || unset PYTEST_ARGS
echo "python -m pytest -rA $PYTEST_ARGS --color=yes ${{ inputs.unittest_directory }}"
python -m pytest -rA $PYTEST_ARGS --color=yes ${{ inputs.unittest_directory }}
# cd "${{ inputs.tests_directory || '.' }}"
[ -n '${{ inputs.unittest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=report/unit/TestReportSummary.xml' || unset PYTEST_ARGS
if [ -n '${{ inputs.coverage_config }}' ]; then
echo "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
else
echo "python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
fi
- name: ☑ Run unit tests (Windows)
if: matrix.system == 'windows'
run: |
$env:ENVIRONMENT_NAME = "${{ matrix.envname }}"
$env:PYTHONPATH = (Get-Location).ToString()
# cd "${{ inputs.tests_directory || '.' }}"
$PYTEST_ARGS = if ("${{ inputs.unittest_xml_artifact }}") { "--junitxml=report/unit/TestReportSummary.xml" } else { "" }
if ("${{ inputs.coverage_config }}") {
Write-Host "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
} else {
Write-Host "python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
}
- name: Convert to XML format (Cobertura)
if: inputs.coverage_xml_artifact != ''
run: coverage xml --data-file=.coverage
- name: Convert to JSON format
if: inputs.coverage_json_artifact != ''
run: coverage json --data-file=.coverage
- name: Convert to HTML format
if: inputs.coverage_html_artifact != ''
run: |
coverage html --data-file=.coverage -d ${{ steps.getVariables.outputs.coverage_report_html_directory }}
rm ${{ steps.getVariables.outputs.coverage_report_html_directory }}/.gitignore
- name: 📤 Upload 'TestReportSummary.xml' artifact
if: inputs.artifact != ''
uses: actions/upload-artifact@v3
if: inputs.unittest_xml_artifact != ''
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.artifact }}-${{ matrix.system }}-${{ matrix.python }}
path: ${{ inputs.tests_directory || '.' }}/TestReportSummary.xml
name: ${{ inputs.unittest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: report/unit/TestReportSummary.xml
if-no-files-found: error
retention-days: 1
# - name: 📤 Upload 'Unit Tests HTML Report' artifact
# if: inputs.unittest_html_artifact != ''
# continue-on-error: true
# uses: actions/upload-artifact@v4
# with:
# name: ${{ inputs.unittest_html_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
# path: ${{ steps.getVariables.outputs.unittest_report_html_directory }}
# if-no-files-found: error
# retention-days: 1
- name: 📤 Upload 'Coverage SQLite Database' artifact
if: inputs.coverage_sqlite_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_sqlite_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: .coverage
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'Coverage XML Report' artifact
if: inputs.coverage_xml_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: ${{ steps.getVariables.outputs.coverage_report_xml }}
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'Coverage JSON Report' artifact
if: inputs.coverage_json_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_json_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: ${{ steps.getVariables.outputs.coverage_report_json }}
if-no-files-found: error
retention-days: 1
- name: 📤 Upload 'Coverage HTML Report' artifact
if: inputs.coverage_html_artifact != ''
continue-on-error: true
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.coverage_html_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
if-no-files-found: error
retention-days: 1

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
@@ -28,7 +28,7 @@ on:
python_version:
description: 'Python version.'
required: false
default: '3.11'
default: '3.12'
type: string
jobs:
@@ -42,7 +42,7 @@ jobs:
uses: actions/checkout@v4
- name: 🐍 Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}

View File

@@ -25,7 +25,7 @@ jobs:
run: echo "${{ matrix.runs-on }}-${{ matrix.python }}" >> artifact.txt
- name: 📤 Upload artifact for ${{ matrix.system }}-${{ matrix.python }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }}-${{ matrix.system }}-${{ matrix.python }}
path: artifact.txt
@@ -42,7 +42,7 @@ jobs:
run: echo "Package" >> package.txt
- name: 📤 Upload artifact for ${{ matrix.system }}-${{ matrix.python }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ fromJson(needs.Params.outputs.artifact_names).package_all }}
path: package.txt

View File

@@ -9,18 +9,15 @@ jobs:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@cov
with:
name: pyDummy
python_version_list: "3.11"
# python_version_list: "3.7 3.8 pypy-3.8 3.9 pypy-3.9 3.10 3.11"
exclude_list: "windows:pypy-3.8 windows:pypy-3.9"
# disable_list: "windows:3.11"
python_version_list: "3.8 3.9 3.10 3.11 3.12 pypy-3.8 pypy-3.9 pypy-3.10"
disable_list: "windows:pypy-3.10"
PlatformTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@cov
with:
name: Platform
python_version_list: ""
system_list: "ubuntu"
# system_list: "ubuntu windows macos mingw32 mingw64 clang64 ucrt64"
system_list: "ubuntu windows macos mingw32 mingw64 clang64 ucrt64"
UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@cov
@@ -28,7 +25,12 @@ jobs:
- UnitTestingParams
with:
jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }}
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
unittest_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}
# coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
# coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
# coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
# coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
PlatformTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@cov
@@ -36,27 +38,24 @@ jobs:
- PlatformTestingParams
with:
jobs: ${{ needs.PlatformTestingParams.outputs.python_jobs }}
tests_directory: ""
unittest_directory: tests/unit/Platform
artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}
# tests_directory: ""
unittest_directory: platform
unittest_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}
unittest_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }}
coverage_sqlite_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }}
coverage_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_xml }}
coverage_json_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_json }}
coverage_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_html }}
Coverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@cov
needs:
- UnitTestingParams
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishCoverageResults:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@cov
needs:
- UnitTesting
- Coverage
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
# Coverage:
# uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@cov
# needs:
# - UnitTestingParams
# with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
# artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
# secrets:
# codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@cov
@@ -69,44 +68,38 @@ jobs:
html_report: 'htmlmypy'
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
PublishCoverageResults:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@cov
needs:
- UnitTestingParams
- UnitTesting
- PlatformTesting
# - Coverage
with:
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@cov
needs:
- UnitTesting
- PlatformTesting
Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@cov
needs:
- UnitTestingParams
- Coverage
- UnitTesting
# - Coverage
- PlatformTesting
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
Release:
uses: pyTooling/Actions/.github/workflows/Release.yml@cov
if: startsWith(github.ref, 'refs/tags')
needs:
- UnitTesting
- Coverage
- StaticTypeCheck
- Package
PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@cov
if: startsWith(github.ref, 'refs/tags')
needs:
- UnitTestingParams
- Release
- Package
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
requirements: -r dist/requirements.txt
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
# VerifyDocs:
# uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@cov
# needs:
@@ -114,33 +107,60 @@ jobs:
# with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
# BuildTheDocs:
# uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@cov
# needs:
# - UnitTestingParams
## - VerifyDocs
# with:
# artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@cov
needs:
- UnitTestingParams
# - VerifyDocs
with:
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@cov
needs:
- UnitTestingParams
# - BuildTheDocs
- Coverage
- BuildTheDocs
# - Coverage
- PublishCoverageResults
- StaticTypeCheck
with:
doc: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
coverage: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
ReleasePage:
uses: pyTooling/Actions/.github/workflows/Release.yml@cov
if: startsWith(github.ref, 'refs/tags')
needs:
- UnitTesting
- PlatformTesting
# - Coverage
# - StaticTypeCheck
- Package
- PublishToGitHubPages
PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@cov
if: startsWith(github.ref, 'refs/tags')
needs:
- UnitTestingParams
- ReleasePage
# - Package
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
requirements: -r dist/requirements.txt
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@cov
needs:
- UnitTestingParams
- PlatformTestingParams
- UnitTesting
- PlatformTesting
- Coverage
# - Coverage
- StaticTypeCheck
# - BuildTheDocs
- PublishToGitHubPages
@@ -150,6 +170,22 @@ jobs:
package: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
remaining: |
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_xml }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_json }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_html }}-*

4
.gitignore vendored
View File

@@ -24,8 +24,8 @@ coverage.xml
# Sphinx
doc/_build/
doc/pyTooling/**/*.*
!doc/pyTooling/index.rst
doc/pyDummy/**/*.*
!doc/pyDummy/index.rst
# BuildTheDocs
doc/_theme/**/*.*

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #

View File

@@ -44,31 +44,31 @@ Complex Example
The following instantiation example creates 3 jobs from the same template, but with differing input parameters. The
first job `UnitTestingParams` might be used to create a job matrix of unit tests. It creates the cross of default
systems (Windows, Ubuntu, MacOS, MinGW64) and the given list of Python versions including some mypy versions. In
systems (Windows, Ubuntu, MacOS, MinGW64, UCRT64) and the given list of Python versions including some mypy versions. In
addition a list of excludes (marked as :deletion:`deletions`) and includes (marked as :addition:`additions`) is handed
over resulting in the following combinations:
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
| Version | 3.7 🔴 | 3.8 🟠 | 3.9 🟡 | 3.10 🟢 | 3.11 🟢 | 3.12.a1 🟣 | pypy-3.7 🔴 | pypy-3.8 🟠 | pypy-3.9 🟡 |
+============+=============+=============+=============+==============+=========================+============+=============+==============================+==============================+
| Windows 🧊 | windows:3.7 | windows:3.8 | windows:3.9 | windows:3.10 | | | | :deletion:`windows:pypy-3.8` | :deletion:`windows:pypy-3.9` |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
| Ubuntu 🐧 | ubuntu:3.7 | ubuntu:3.8 | ubuntu:3.9 | ubuntu:3.10 | :addition:`ubuntu:3.11` | | | ubuntu:pypy-3.8 | ubuntu:pypy-3.9 |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
| MacOS 🍎 | macos:3.7 | macos:3.8 | macos:3.9 | macos:3.10 | :addition:`macos:3.11` | | | macos:pypy-3.8 | macos:pypy-3.9 |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| Version | 3.8 🔴 | 3.9 🟠 | 3.10 🟡 | 3.11 🟢 | 3.12 🟢 | 3.13.a1 🟣 | pypy-3.8 🔴 | pypy-3.9 🟠 | pypy-3.10 🟡 |
+============+=============+=============+==============+==============+=========================+============+=============+==============================+===============================+
| Windows 🧊 | windows:3.8 | windows:3.9 | windows:3.10 | windows:3.11 | | | | :deletion:`windows:pypy-3.9` | :deletion:`windows:pypy-3.10` |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| Ubuntu 🐧 | ubuntu:3.8 | ubuntu:3.9 | ubuntu:3.10 | ubuntu:3.11 | :addition:`ubuntu:3.12` | | | ubuntu:pypy-3.9 | ubuntu:pypy-3.10 |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| MacOS 🍎 | macos:3.8 | macos:3.9 | macos:3.10 | macos:3.11 | :addition:`macos:3.12` | | | macos:pypy-3.9 | macos:pypy-3.10 |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| MSYS 🟪 | | | | | | | | | |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| MinGW32 ⬛ | | | | | | | | | |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
| MinGW64 🟦 | | | | mingw64:3.10 | | | | | |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| MinGW64 🟦 | | | | mingw64:3.11 | | | | | |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| Clang32 🟫 | | | | | | | | | |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| Clang64 🟧 | | | | | | | | | |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| UCRT64 🟨 | | | | | | | | | |
+------------+-------------+-------------+-------------+--------------+-------------------------+------------+-------------+------------------------------+------------------------------+
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
.. code-block:: yaml
@@ -84,22 +84,22 @@ over resulting in the following combinations:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0
with:
name: pyTooling
python_version_list: "3.7 3.8 3.9 3.10 pypy-3.8 pypy-3.9"
include_list: "ubuntu:3.11 macos:3.11"
exclude_list: "windows:pypy-3.8 windows:pypy-3.9"
python_version_list: "3.8 3.9 3.10 3.11 pypy-3.9 pypy-3.10"
include_list: "ubuntu:3.12 macos:3.12"
exclude_list: "windows:pypy-3.9 windows:pypy-3.10"
PerformanceTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0
with:
name: pyTooling
python_version_list: "3.10 3.11"
python_version_list: "3.11 3.12"
system_list: "ubuntu windows macos"
PlatformTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@dev
with:
name: pyTooling
python_version_list: "3.10"
python_version_list: "3.12"
system_list: "ubuntu windows macos mingw32 mingw64 clang64 ucrt64"
Parameters
@@ -125,7 +125,7 @@ python_version
+----------------+----------+----------+----------+
| Parameter Name | Required | Type | Default |
+================+==========+==========+==========+
| python_version | optional | string | ``3.11`` |
| python_version | optional | string | ``3.12`` |
+----------------+----------+----------+----------+
Python version to be used for all jobs requiring a single Python version.
@@ -134,52 +134,54 @@ Python version to be used for all jobs requiring a single Python version.
python_version_list
===================
+----------------------+----------+----------+---------------------------+
+----------------------+----------+----------+----------------------------+
| Parameter Name | Required | Type | Default |
+======================+==========+==========+===========================+
| python_version_list | optional | string | ``3.7 3.8 3.9 3.10 3.11`` |
+----------------------+----------+----------+---------------------------+
+======================+==========+==========+============================+
| python_version_list | optional | string | ``3.8 3.9 3.10 3.11 3.12`` |
+----------------------+----------+----------+-------------------------- -+
Space separated list of CPython versions and/or mypy version to run tests with.
**Possible values:**
* ``3.6``, ``3.7``, ``3.8``, ``3.9``, ``3.10`` , ``3.11``, ``3.12``
* ``pypy-3.7``, ``pypy-3.8``, ``pypy-3.9``
* ``3.7``, ``3.8``, ``3.9``, ``3.10`` , ``3.11``, ``3.12``, ``3.13``
* ``pypy-3.7``, ``pypy-3.8``, ``pypy-3.9``, ``pypy-3.10``
+------+-----------+------------------+-----------------------------------------+
| Icon | Version | Maintained until | Comments |
+======+===========+==================+=========================================+
| ⚫ | 3.6 | 2021.12.23 | :red:`outdated` |
| ⚫ | 3.7 | 2023.06.27 | :red:`outdated` |
+------+-----------+------------------+-----------------------------------------+
| 🔴 | 3.7 | 2023.06.27 | |
| 🔴 | 3.8 | 2024.10 | |
+------+-----------+------------------+-----------------------------------------+
| 🟠 | 3.8 | 2024.10 | |
| 🟠 | 3.9 | 2025.10 | |
+------+-----------+------------------+-----------------------------------------+
| 🟡 | 3.9 | 2025.10 | |
| 🟡 | 3.10 | 2026.10 | |
+------+-----------+------------------+-----------------------------------------+
| 🟢 | 3.10 | 2026.10 | |
| 🟢 | 3.11 | 2027.10 | |
+------+-----------+------------------+-----------------------------------------+
| 🟢 | 3.11 | 2027.10 | :green:`latest` |
| 🟢 | 3.12 | 2028.10 | :green:`latest` |
+------+-----------+------------------+-----------------------------------------+
| 🟣 | 3.12 | 2028.10 | Python 3.12 alpha (or RC) will be used. |
| 🟣 | 3.13 | 2029.10 | Python 3.13 alpha (or RC) will be used. |
+------+-----------+------------------+-----------------------------------------+
|🔴 | pypy-3.7 | ????.?? | |
| | pypy-3.7 | ????.?? | |
+------+-----------+------------------+-----------------------------------------+
|🟠 | pypy-3.8 | ????.?? | |
|🔴 | pypy-3.8 | ????.?? | |
+------+-----------+------------------+-----------------------------------------+
|🟡 | pypy-3.9 | ????.?? | |
|🟠 | pypy-3.9 | ????.?? | |
+------+-----------+------------------+-----------------------------------------+
| ⟲🟡 | pypy-3.10 | ????.?? | |
+------+-----------+------------------+-----------------------------------------+
system_list
===========
+----------------+----------+----------+----------------------------------+
+----------------+----------+----------+-----------------------------------------+
| Parameter Name | Required | Type | Default |
+================+==========+==========+==================================+
| system_list | optional | string | ``ubuntu windows mingw64 macos`` |
+----------------+----------+----------+----------------------------------+
+================+==========+==========+=========================================+
| system_list | optional | string | ``ubuntu windows macos mingw64 ucrt64`` |
+----------------+----------+----------+-----------------------------------------+
Space separated list of systems to run tests on.
@@ -193,9 +195,9 @@ Space separated list of systems to run tests on.
+======+===========+==============================+=================================================================+
| 🧊 | Windows | Windows Server 2022 (latest) | |
+------+-----------+------------------------------+-----------------------------------------------------------------+
| 🐧 | Ubuntu | Ubuntu 20.04 (LTS) (latest) | While this marked latest, Ubuntu 22.02 LTS is already provided. |
| 🐧 | Ubuntu | Ubuntu 22.04 (LTS) (latest) | |
+------+-----------+------------------------------+-----------------------------------------------------------------+
| 🍎 | MacOS | macOS Big Sur 11 (latest) | While this marked latest, macOS Monterey 12 is already provided.|
| 🍎 | MacOS | macOS Monterey 12 (latest) | While this marked latest, macOS Ventura 13 is already provided. |
+------+-----------+------------------------------+-----------------------------------------------------------------+
| 🟪 | MSYS | | |
+------+-----------+------------------------------+-----------------------------------------------------------------+
@@ -210,6 +212,7 @@ Space separated list of systems to run tests on.
| 🟨 | UCRT64 | | |
+------+-----------+------------------------------+-----------------------------------------------------------------+
Source: `Images provided by GitHub <https://github.com/actions/runner-images>`__
include_list
============
@@ -370,6 +373,9 @@ A dictionary of artifact names sharing a common prefix.
The supported artifacts are:
* ``unittesting_xml`` - UnitTesting XML summary report
* ``unittesting_html`` - UnitTesting HTML summary report
* ``codecoverage_sqlite`` - Code Coverage internal database (SQLite)
* ``codecoverage_json`` - Code Coverage JSON report
* ``codecoverage_xml`` - Code Coverage XML report
* ``codecoverage_html`` - Code Coverage HTML report
* ``statictyping_html`` - Static Type Checking HTML report

160
doc/_templates/autoapi/module.rst vendored Normal file
View File

@@ -0,0 +1,160 @@
.. # Template modified by Patrick Lehmann
* removed automodule on top, because private members are activated for autodoc (no doubled documentation).
* Made sections like 'submodules' bold text, but no headlines to reduce number of ToC levels.
{{ '=' * node.name|length }}
{{ node.name }}
{{ '=' * node.name|length }}
.. automodule:: {{ node.name }}
{##}
{%- block modules -%}
{%- if subnodes %}
**Submodules**
.. toctree::
:maxdepth: 1
{% for item in subnodes %}
{{ item.name }}
{%- endfor %}
{##}
{%- endif -%}
{%- endblock -%}
{##}
.. currentmodule:: {{ node.name }}
{##}
{%- if node.variables %}
**Variables**
{% for item, obj in node.variables.items() -%}
- :py:data:`{{ item }}`
{#{ obj|summary }#}
{% endfor -%}
{%- endif -%}
{%- if node.functions %}
**Functions**
{% for item, obj in node.functions.items() -%}
- :py:func:`{{ item }}`:
{{ obj|summary }}
{% endfor -%}
{%- endif -%}
{%- if node.exceptions %}
**Exceptions**
{% for item, obj in node.exceptions.items() -%}
- :py:exc:`{{ item }}`:
{{ obj|summary }}
{% endfor -%}
{%- endif -%}
{%- if node.classes %}
**Classes**
{% for item, obj in node.classes.items() -%}
- :py:class:`{{ item }}`:
{{ obj|summary }}
{% endfor -%}
{%- endif -%}
{%- block variables -%}
{%- if node.variables %}
---------------------
**Variables**
{#% for item, obj in node.variables.items() -%}
- :py:data:`{{ item }}`
{% endfor -%#}
{% for item, obj in node.variables.items() %}
.. autodata:: {{ item }}
:annotation:
.. code-block:: text
{{ obj|pprint|indent(6) }}
{##}
{%- endfor -%}
{%- endif -%}
{%- endblock -%}
{%- block functions -%}
{%- if node.functions %}
---------------------
**Functions**
{% for item in node.functions %}
.. autofunction:: {{ item }}
{##}
{%- endfor -%}
{%- endif -%}
{%- endblock -%}
{%- block exceptions -%}
{%- if node.exceptions %}
---------------------
**Exceptions**
{#% for item, obj in node.exceptions.items() -%}
- :py:exc:`{{ item }}`:
{{ obj|summary }}
{% endfor -%#}
{% for item in node.exceptions %}
.. autoexception:: {{ item }}
.. rubric:: Inheritance
.. inheritance-diagram:: {{ item }}
:parts: 1
{##}
{%- endfor -%}
{%- endif -%}
{%- endblock -%}
{%- block classes -%}
{%- if node.classes %}
---------------------
**Classes**
{#% for item, obj in node.classes.items() -%}
- :py:class:`{{ item }}`:
{{ obj|summary }}
{% endfor -%#}
{% for item in node.classes %}
.. autoclass:: {{ item }}
:members:
:private-members:
:special-members:
:inherited-members:
:exclude-members: __weakref__
.. rubric:: Inheritance
.. inheritance-diagram:: {{ item }}
:parts: 1
{##}
{%- endfor -%}
{%- endif -%}
{%- endblock -%}

14
doc/_templates/autoapi/package.rst vendored Normal file
View File

@@ -0,0 +1,14 @@
.. # Template created by Patrick Lehmann
Python Class Reference
######################
Reference of all packages and modules:
.. automodule:: {{ node.name }}
.. toctree::
:maxdepth: 1
{% for item in subnodes %}
{{ item.name }}
{%- endfor %}

View File

@@ -13,7 +13,7 @@ ROOT = Path(__file__).resolve().parent
sys_path.insert(0, abspath("."))
sys_path.insert(0, abspath(".."))
#sys_path.insert(0, abspath("../pyTooling"))
sys_path.insert(0, abspath("../pyDummy"))
sys_path.insert(0, abspath("_extensions"))
@@ -25,7 +25,7 @@ sys_path.insert(0, abspath("_extensions"))
# built documents.
project = "Actions"
packageInformationFile = Path(f"../{project}/__init__.py")
packageInformationFile = Path(f"../pyDummy/__init__.py")
versionInformation = extractVersionInformation(packageInformationFile)
author = versionInformation.Author
@@ -173,9 +173,11 @@ latex_documents = [
# ==============================================================================
extensions = [
# Standard Sphinx extensions
"sphinx.ext.autodoc",
"sphinx.ext.coverage",
"sphinx.ext.extlinks",
"sphinx.ext.intersphinx",
"sphinx.ext.inheritance_diagram",
"sphinx.ext.todo",
"sphinx.ext.graphviz",
"sphinx.ext.mathjax",
@@ -185,6 +187,9 @@ extensions = [
"sphinxcontrib.mermaid",
# Other extensions
"sphinx_fontawesome",
"sphinx_autodoc_typehints",
"sphinx_inline_tabs",
"autoapi.sphinx",
]
@@ -216,9 +221,9 @@ autodoc_typehints = "both"
# Sphinx.Ext.ExtLinks
# ==============================================================================
extlinks = {
"gh": ("https://GitHub.com/%s", "gh:"),
"ghissue": ("https://GitHub.com/pyTooling/Actions/issues/%s", "issue #"),
"ghpull": ("https://GitHub.com/pyTooling/Actions/pull/%s", "pull request #"),
"gh": ("https://GitHub.com/%s", "gh:%s"),
"ghissue": ("https://GitHub.com/pyTooling/Actions/issues/%s", "issue #%s"),
"ghpull": ("https://GitHub.com/pyTooling/Actions/pull/%s", "pull request #%s"),
"ghsrc": ("https://GitHub.com/pyTooling/Actions/blob/main/%s", None),
"wiki": ("https://en.wikipedia.org/wiki/%s", None),
}
@@ -239,6 +244,18 @@ mermaid_params = [
mermaid_verbose = True
# ==============================================================================
# Sphinx.Ext.Inheritance_Diagram
# ==============================================================================
inheritance_node_attrs = {
# "shape": "ellipse",
# "fontsize": 14,
# "height": 0.75,
"color": "dodgerblue1",
"style": "filled"
}
# ==============================================================================
# Sphinx.Ext.ToDo
# ==============================================================================
@@ -251,3 +268,15 @@ todo_link_only = True
# Sphinx.Ext.Coverage
# ==============================================================================
coverage_show_missing_items = True
# ==============================================================================
# AutoAPI.Sphinx
# ==============================================================================
autoapi_modules = {
"pyDummy": {
"template": "module",
"output": "pyDummy",
"override": True
}
}

4
doc/coverage/index.rst Normal file
View File

@@ -0,0 +1,4 @@
Code Coverage Report
####################
*Placeholder for the Coverage report generated with* ``pytest`` *and* ``coverage``.

View File

@@ -122,14 +122,6 @@ License
The accompanying documentation is licensed under **Creative Commons - Attribution 4.0 (CC-BY 4.0)**.
------------------------------------
.. |docdate| date:: %b %d, %Y - %H:%M
.. only:: html
This document was generated on |docdate|.
.. toctree::
:caption: Introduction
:hidden:
@@ -171,6 +163,19 @@ License
JobTemplate/Release
JobTemplate/ArtifactCleanUp
.. raw:: latex
\part{pyDummy Example}
.. toctree::
:caption: pyDummy Example
:hidden:
pyDummy/pyDummy
Unittest Report ➚ <unittests/index>
Coverage Report ➚ <coverage/index>
Static Type Check Report ➚ <typing/index>
.. raw:: latex
\part{Appendix}

0
doc/pyDummy/.gitempty Normal file
View File

View File

@@ -3,7 +3,8 @@
pyTooling >= 5.0.0, < 6.0
# Enforce latest version on ReadTheDocs
sphinx >=5.3, < 6.0
sphinx >= 7.1, < 8.0
docutils >= 0.18.0, < 0.19.0
# Sphinx Extenstions
#sphinx.ext.coverage
@@ -12,12 +13,8 @@ sphinxcontrib-mermaid>=0.9.2
#sphinxcontrib-seqdiag>=0.8.5
#sphinxcontrib-textstyle>=0.2.1
#sphinxcontrib-spelling>=2.2.0
autoapi
sphinx_fontawesome>=0.0.6
sphinx_autodoc_typehints>=1.19.5
autoapi >= 2.0.1
sphinx_fontawesome >= 0.0.6
sphinx-inline-tabs >= 2023.4.21
sphinx_autodoc_typehints >= 1.24.0
# changelog>=0.3.5
# BuildTheDocs Extensions (mostly patched Sphinx extensions)
# For pyTooling.Configuration.YAML documentation
ruamel.yaml>=0.17

8
doc/typing/index.rst Normal file
View File

@@ -0,0 +1,8 @@
Static Type Checking Report
###########################
*Placeholder for the Static Type Checking report generated with* ``mypy``.
.. #raw:: html
<iframe src="../../../../report/typing/index.html" width="100%" height="500px" style="border:none;"/>

4
doc/unittests/index.rst Normal file
View File

@@ -0,0 +1,4 @@
UnitTest Report
###############
*Placeholder for the unittest report generated with* ``pytest``.

View File

@@ -11,7 +11,7 @@
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Bötzingen, Germany #
# Copyright 2017-2024 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. #
@@ -28,24 +28,74 @@
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""
A module for a set of dummy classes.
"""
__author__ = "Patrick Lehmann"
__email__ = "Paebbels@gmail.com"
__copyright__ = "2017-2023, Patrick Lehmann"
__copyright__ = "2017-2024, Patrick Lehmann"
__license__ = "Apache License, Version 2.0"
__version__ = "0.1.0"
__keywords__ = ["dummy"]
__version__ = "0.4.4"
__keywords__ = ["GitHub Actions"]
__issue_tracker__ = "https://GitHub.com/pyTooling/Actions/issues"
from pyTooling.Decorators import export
from pyTooling.Decorators import export, readonly
from pyTooling.Platform import Platform
@export
class Application:
_value: int
class Base:
"""
A base-class for dummy applications.
"""
_value: int #: An internal value.
def __init__(self) -> None:
self._value = 1
"""
Initializes the base-class.
"""
self._value = 0
@property
@readonly
def Value(self) -> int:
"""
Read-only property to return the internal value.
:return: Internal value.
"""
return self._value
@export
class Application(Base):
"""
A dummy application for demonstration purposes.
"""
def __init__(self) -> None:
"""
Initializes the dummy application.
"""
super().__init__()
platform = Platform()
if platform.IsNativeLinux:
self._value += 1
elif platform.IsNativeMacOS:
self._value += 2
elif platform.IsNativeWindows:
self._value += 3
elif platform.IsMSYSOnWindows:
self._value += 11
elif platform.IsMinGW32OnWindows:
self._value += 12
elif platform.IsMinGW64OnWindows:
self._value += 13
elif platform.IsUCRT64OnWindows:
self._value += 14
elif platform.IsClang32OnWindows:
self._value += 15
elif platform.IsClang64OnWindows:
self._value += 16

View File

@@ -11,7 +11,7 @@ line-length = 120
[tool.mypy]
files = ["pyDummy"]
python_version = "3.11"
python_version = "3.12"
#ignore_missing_imports = true
strict = true
pretty = true
@@ -32,10 +32,14 @@ filterwarnings = [
[tool.coverage.run]
branch = true
relative_files = true
omit = [
"*site-packages*",
"setup.py",
"tests/*"
"tests/benchmark/*",
"tests/performance/*",
"tests/platform/*",
"tests/unit/*"
]
[tool.coverage.report]

View File

@@ -3,7 +3,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #

View File

@@ -3,7 +3,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #

View File

@@ -5,7 +5,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #

View File

@@ -11,7 +11,7 @@
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Bötzingen, Germany #
# Copyright 2017-2024 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. #
@@ -38,7 +38,8 @@ packageName = "pyDummy"
packageDirectory = packageName
packageInformationFile = Path(f"{packageDirectory}/__init__.py")
setup(**DescribePythonPackageHostedOnGitHub(
# setup(**
DescribePythonPackageHostedOnGitHub(
packageName=packageName,
description="pyDummy is a test package to verify GitHub actions for Python projects.",
gitHubNamespace=gitHubNamespace,
@@ -47,4 +48,5 @@ setup(**DescribePythonPackageHostedOnGitHub(
dataFiles={
packageName: ["py.typed"]
}
))
)
# )

View File

@@ -11,7 +11,7 @@
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Bötzingen, Germany #
# Copyright 2017-2024 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. #
@@ -28,12 +28,12 @@
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""Unit tests for TBD."""
from os import getenv as os_getenv
from pytest import mark
from unittest import TestCase
from pyTooling.Platform import Platform
from pytest import mark
from pyTooling.Common import CurrentPlatform
from pyDummy import Application
if __name__ == "__main__": # pragma: no cover
@@ -42,75 +42,57 @@ if __name__ == "__main__": # pragma: no cover
exit(1)
class AnyPlatform(TestCase):
expected = os_getenv("ENVIRONMENT_NAME", default="Windows (x86-64)")
class PlatformTesting(TestCase):
@mark.skipif(not CurrentPlatform.IsNativeLinux, reason="Skipped, if current platform isn't native Linux.")
def test_ApplicationOnNativeLinux(self):
app = Application()
@mark.skipif(os_getenv("ENVIRONMENT_NAME", "skip") == "skip", reason="Skipped when environment variable 'ENVIRONMENT_NAME' isn't set.")
def test_PlatformString(self) -> None:
platform = Platform()
self.assertEqual(1, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsNativeMacOS, reason="Skipped, if current platform isn't native macOS.")
def test_ApplicationOnNativeMacOS(self):
app = Application()
@mark.skipif("Linux (x86-64)" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_NativeLinux' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_NativeLinux(self) -> None:
platform = Platform()
self.assertEqual(2, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsNativeWindows, reason="Skipped, if current platform isn't native Windows.")
def test_ApplicationOnNativeWindows(self):
app = Application()
@mark.skipif("MacOS (x86-64)" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_NativeMacOS' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_NativeMacOS(self) -> None:
platform = Platform()
self.assertEqual(3, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsMSYSOnWindows, reason="Skipped, if current platform isn't MSYS on Windows.")
def test_ApplicationOnMSYS2OnWindows(self):
app = Application()
@mark.skipif("Windows (x86-64)" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_NativeWindows' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_NativeWindows(self) -> None:
platform = Platform()
self.assertEqual(11, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsMinGW32OnWindows, reason="Skipped, if current platform isn't MinGW32 on Windows.")
def test_ApplicationOnMinGW32OnWindows(self):
app = Application()
@mark.skipif("Windows+MSYS2 (x86-64) - MSYS" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_MSYS' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_MSYS(self) -> None:
platform = Platform()
self.assertEqual(12, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsMinGW64OnWindows, reason="Skipped, if current platform isn't MinGW64 on Windows.")
def test_ApplicationOnMinGW64OnWindows(self):
app = Application()
@mark.skipif("Windows+MSYS2 (x86-64) - MinGW32" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_MinGW32' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_MinGW32(self) -> None:
platform = Platform()
self.assertEqual(13, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsUCRT64OnWindows, reason="Skipped, if current platform isn't UCRT64 on Windows.")
def test_ApplicationOnURTC64OnWindows(self):
app = Application()
@mark.skipif("Windows+MSYS2 (x86-64) - MinGW64" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_MinGW64' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_MinGW64(self) -> None:
platform = Platform()
self.assertEqual(14, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsClang32OnWindows, reason="Skipped, if current platform isn't Clang32 on Windows.")
def test_ApplicationOnClang32OnWindows(self):
app = Application()
@mark.skipif("Windows+MSYS2 (x86-64) - UCRT64" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_UCRT64' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_UCRT64(self) -> None:
platform = Platform()
self.assertEqual(15, app.Value)
print()
print(platform)
@mark.skipif(not CurrentPlatform.IsClang64OnWindows, reason="Skipped, if current platform isn't Clang64 on Windows.")
def test_ApplicationOnClang64OnWindows(self):
app = Application()
@mark.skipif("Windows+MSYS2 (x86-64) - Clang32" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_Clang32' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_Clang32(self) -> None:
platform = Platform()
print()
print(platform)
@mark.skipif("Windows+MSYS2 (x86-64) - Clang64" != os_getenv("ENVIRONMENT_NAME", "skip"), reason=f"Skipped 'test_Clang64' when environment variable 'ENVIRONMENT_NAME' doesn't match. {os_getenv('ENVIRONMENT_NAME', 'skip')}")
def test_Clang64(self) -> None:
platform = Platform()
print()
print(platform)
self.assertEqual(16, app.Value)

View File

@@ -1,13 +1,13 @@
-r ../requirements.txt
# Coverage collection
Coverage >= 7.3
Coverage >= 7.4
# Test Runner
pytest >= 7.4.0
pytest-cov >= 4.1.0
# Static Type Checking
mypy >= 1.5.0
typing_extensions >= 4.7.1
lxml>=4.9
mypy >= 1.8.0
typing_extensions >= 4.9.0
lxml >= 5.0

View File

@@ -11,7 +11,7 @@
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Bötzingen, Germany #
# Copyright 2017-2024 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. #
@@ -37,4 +37,4 @@ class Instantiation(TestCase):
def test_Application(self):
app = Application()
self.assertEqual(1, app.Value)
self.assertGreater(app.Value, 0)

View File

@@ -11,7 +11,7 @@
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2023 Patrick Lehmann - Bötzingen, Germany #
# Copyright 2017-2024 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. #
@@ -28,4 +28,4 @@
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""Test code for pyTooling."""
"""Test code for pyDummy."""

View File

@@ -4,7 +4,7 @@
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2023 The pyTooling Authors #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #