From b78cbae4226f3245369353795f5f2546ed380677 Mon Sep 17 00:00:00 2001 From: cclecle Date: Thu, 28 Sep 2023 23:34:54 +0100 Subject: [PATCH 1/3] fix: correct the code to add non existing keys in COD4 cfg files --- src/pygamecfg/core_gamecfg.py | 14 +++++++++++--- src/pygamecfg/game_cod4.py | 17 ++++++++++------- test/data/COD4/main/server.cfg | 2 +- test/test_cod4.py | 15 ++++++++++++--- test/test_ut99.py | 3 --- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/pygamecfg/core_gamecfg.py b/src/pygamecfg/core_gamecfg.py index fbd7d51..915c5f8 100644 --- a/src/pygamecfg/core_gamecfg.py +++ b/src/pygamecfg/core_gamecfg.py @@ -19,6 +19,14 @@ from abc import ABCMeta, abstractmethod from enum import Enum +class GameCfgException(Exception): + """Standard Exception to catch non existing key in configuration file""" + + +class OptionNotFoundError(GameCfgException): + """Standard Exception to catch non existing configuration option""" + + class OptionType(Enum): """Supported option data type""" @@ -145,7 +153,7 @@ class GameOptions_Factory: with _option(self.GameRootDir, self.ConfigFileRelPath) as _optionInst: _optionInst.set(_optionInst.format(value)) return - raise RuntimeError("Option not found") + raise OptionNotFoundError("Option not found") def rem(self, OptionName: str, value: Union[None, str]) -> None: """generic rem function (API call)""" @@ -154,7 +162,7 @@ class GameOptions_Factory: with _option(self.GameRootDir, self.ConfigFileRelPath) as _optionInst: _optionInst.rem(value) return - raise RuntimeError("Option not found") + raise OptionNotFoundError("Option not found") def get(self, OptionName: str) -> Union[str, list[str]]: """generic get function (API call)""" @@ -162,7 +170,7 @@ class GameOptions_Factory: if _option.szOptionName == OptionName: with _option(self.GameRootDir, self.ConfigFileRelPath) as _optionInst: return _optionInst.get() - raise RuntimeError("Option not found") + raise OptionNotFoundError("Option not found") def GameOptions_Factory_Register(cls: type[GameOption]) -> type[GameOption]: diff --git a/src/pygamecfg/game_cod4.py b/src/pygamecfg/game_cod4.py index 08aa516..15db995 100644 --- a/src/pygamecfg/game_cod4.py +++ b/src/pygamecfg/game_cod4.py @@ -17,7 +17,11 @@ import re from os.path import join from os import linesep -from .core_gamecfg import GameOptions_Factory_Register, GameOption, OptionType +from .core_gamecfg import GameOptions_Factory_Register, GameOption, OptionType, GameCfgException + + +class COD4KeyNotFoundError(GameCfgException): + """Exception to catch non existing configuration key in COD4 configuration file""" class GameOption_COD4(GameOption): @@ -27,7 +31,7 @@ class GameOption_COD4(GameOption): szOptionName: str = "" szKeyName: str = "" bDblQuoted: bool = False - szPrefix = "" + szPrefix: str = "" def __init__(self, GameRootDir: str, ConfigFileRelPath: str) -> None: super().__init__(GameRootDir, ConfigFileRelPath) @@ -47,9 +51,8 @@ class GameOption_COD4(GameOption): FinalValue: str = value if self.bDblQuoted: FinalValue = '"' + FinalValue + '"' - if self.szPrefix: + if self.szPrefix != "": FinalValue = self.szPrefix + " " + self.szKeyName + " " + FinalValue + linesep - bfound = False newFile = "" @@ -66,7 +69,7 @@ class GameOption_COD4(GameOption): if not bfound: # write new key at the top of the file to be sure we do not erase the map / map_rotate cmd - newFile = value + newFile + newFile = FinalValue + newFile self.cfgfile.close() with open(self.mainConfigFilePath, "w", encoding="utf8") as ofile: @@ -89,7 +92,7 @@ class GameOption_COD4(GameOption): else: newFile += line if not bfound: - raise RuntimeError("Option not found in file") + raise COD4KeyNotFoundError("Option not found in file") self.cfgfile.close() with open(self.mainConfigFilePath, "w", encoding="utf8") as ofile: @@ -113,7 +116,7 @@ class GameOption_COD4(GameOption): res = result.groupdict()["value"] bfound = True if not bfound: - raise RuntimeError("Option not found in file") + raise COD4KeyNotFoundError("Option not found in file") return res diff --git a/test/data/COD4/main/server.cfg b/test/data/COD4/main/server.cfg index c91ce60..1b4ac75 100644 --- a/test/data/COD4/main/server.cfg +++ b/test/data/COD4/main/server.cfg @@ -24,7 +24,7 @@ set g_log "games_mp.log" set sv_log_damage "1" set sv_statusfile "serverstatus.xml" -set net_port 28960 +//set net_port 28960 set sv_minPing "0" diff --git a/test/test_cod4.py b/test/test_cod4.py index c90dc03..ee586ae 100644 --- a/test/test_cod4.py +++ b/test/test_cod4.py @@ -15,14 +15,12 @@ import shutil from src import pygamecfg from src.pygamecfg.__main__ import fct_main +from src.pygamecfg.game_cod4 import COD4KeyNotFoundError testdir_path = Path(__file__).parent.resolve() class Testtest_cod4(unittest.TestCase): - def tearDown(self) -> None: - self.CleanTmp() - def setUp(self) -> None: chdir(testdir_path.parent.resolve()) self.CleanTmp() @@ -65,3 +63,14 @@ class Testtest_cod4(unittest.TestCase): self.assertEqual("", capted_stderr.getvalue()) # check if other key still there / untouched self.test_normal_READ_sv_mapRotation() + + def test_defect_READ_net_port_NONEXISTS(self): + with self.assertRaises(COD4KeyNotFoundError): + fct_main(["-g", "cod4", "-b", "test/tmp/COD4", "GetOption", "net_port"]) + + def test_normal_WRITE_net_port_NONEXISTS(self): + fct_main(["-g", "cod4", "-b", "test/tmp/COD4", "SetOption", "net_port", "132"]) + with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr: + fct_main(["-g", "cod4", "-b", "test/tmp/COD4", "GetOption", "net_port"]) + self.assertEqual("132\n", capted_stdout.getvalue()) + self.assertEqual("", capted_stderr.getvalue()) diff --git a/test/test_ut99.py b/test/test_ut99.py index 39ee258..369962c 100644 --- a/test/test_ut99.py +++ b/test/test_ut99.py @@ -20,9 +20,6 @@ testdir_path = Path(__file__).parent.resolve() class Testtest_ut99(unittest.TestCase): - def tearDown(self) -> None: - self.CleanTmp() - def setUp(self) -> None: chdir(testdir_path.parent.resolve()) self.CleanTmp() From 2b918837fd4645b98033c2fad85c04470ef8aa69 Mon Sep 17 00:00:00 2001 From: cclecle Date: Thu, 28 Sep 2023 23:38:05 +0100 Subject: [PATCH 2/3] ignore tmp unittest files from git --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 221ee37..e395bb1 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,5 @@ helpers-results .coverage /.mypy_cache/ .coverage -.mypy_cache \ No newline at end of file +.mypy_cache +test/tmp \ No newline at end of file From d0cdad663df5707a5bf2e7de414f3ad7a9f910bb Mon Sep 17 00:00:00 2001 From: cclecle Date: Fri, 29 Sep 2023 22:51:50 +0100 Subject: [PATCH 3/3] chore: switch from local helpers to common library --- Jenkinsfile | 61 ++++----- RUN_changelog.launch | 16 --- RUN_complexity.launch | 7 +- RUN_mkdocs.launch | 10 +- RUN_quality.launch | 7 +- RUN_unittest.launch | 7 +- helpers/.gitignore | 1 - helpers/__init__.py | 7 - helpers/__main__.py | 108 ---------------- helpers/complexity_check.py | 70 ---------- helpers/doc_gen.py | 98 -------------- helpers/helper_base.py | 82 ------------ helpers/quality_check.py | 247 ------------------------------------ helpers/types_check.py | 60 --------- helpers/unit_test.py | 81 ------------ helpers_proxy/__main__.py | 5 + pyproject.toml | 12 +- pyproject.toml.bak | 68 ---------- 18 files changed, 59 insertions(+), 888 deletions(-) delete mode 100644 RUN_changelog.launch delete mode 100644 helpers/.gitignore delete mode 100644 helpers/__init__.py delete mode 100644 helpers/__main__.py delete mode 100644 helpers/complexity_check.py delete mode 100644 helpers/doc_gen.py delete mode 100644 helpers/helper_base.py delete mode 100644 helpers/quality_check.py delete mode 100644 helpers/types_check.py delete mode 100644 helpers/unit_test.py create mode 100644 helpers_proxy/__main__.py delete mode 100644 pyproject.toml.bak diff --git a/Jenkinsfile b/Jenkinsfile index 13ee83d..12ce00e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -27,7 +27,7 @@ def _bDraft = false // release content / changelog management def _bAutoChangelog = true //Not supported yet def _ReleaseContent_Title = "# _CI/CD Automatic Release_" -def bPushMasterOnPypi = false +def bPushMasterOnPypi = true // full rebuild toogle def _bFullRebuilt = true def _MkDocsWebURL = "dabauto--mkdocs-web.dmz.chacha.home/mkdocs-web/" @@ -183,8 +183,12 @@ pipeline { sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python TEST_ENV") sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python TOOLS_ENV") - sh(". ~/BUILD_ENV/bin/activate && pip install --upgrade setuptools build pip copier jinja2-slug toml") + sh(". ~/BUILD_ENV/bin/activate && pip install --upgrade setuptools build pip") + sh(". ~/BUILD_ENV/bin/activate && pip install --upgrade 'copier==8.*' jinja2-slug toml") + + sh(". ~/TEST_ENV/bin/activate && pip install --upgrade pip") + sh(". ~/TOOLS_ENV/bin/activate && pip install --upgrade pip") sh(". ~/TOOLS_ENV/bin/activate && pip install simple_rest_client requests twine packaging") script { @@ -341,7 +345,7 @@ pipeline { |'''.strip() | |import copier - |copier.run_copy("./", "../_gitrepo",vcs_ref="HEAD",use_prereleases=True,defaults=True,cleanup_on_error=False) + |copier.run_copy("./", "../_gitrepo",vcs_ref="HEAD",use_prereleases=True,defaults=True,cleanup_on_error=False,unsafe=True) | |__EOWRAPPER__ """.stripMargin()) @@ -409,31 +413,31 @@ pipeline { stage("CheckCode") { steps { dir("gitrepo") { - sh(". ~/TEST_ENV/bin/activate && python -m helpers --type-check --quality-check") + sh(". ~/TEST_ENV/bin/activate && python -m chacha_cicd_helper --typecheck --qualitycheck") script { - def jsonObj = readJSON file: "helpers-results/quality_check/metrics.json" + def jsonObj = readJSON file: "helpers-results/cl_quality_check/metrics.json" quality_score = new BigDecimal(jsonObj["GlobalScore"]) sz_quality_score = quality_score.setScale(2, RoundingMode.HALF_EVEN).toString() badge_quality.setStatus(sz_quality_score) badge_quality.setColor(getColorScale(quality_score)) } - sh(". ~/TEST_ENV/bin/activate && python -m helpers --complexity-check") + sh(". ~/TEST_ENV/bin/activate && python -m chacha_cicd_helper --complexitycheck") } } post { always { dir("gitrepo") { - publishCoverage adapters: [cobertura(mergeToOneReport: true, path: "helpers-results/types_check/cobertura.xml")] - junit 'helpers-results/types_check/junit.xml' + publishCoverage adapters: [cobertura(mergeToOneReport: true, path: "helpers-results/cl_types_check/cobertura.xml")] + junit 'helpers-results/cl_types_check/junit.xml' publishHTML([ - reportDir: "helpers-results/quality_check", + reportDir: "helpers-results/cl_quality_check", reportFiles: "report.html", reportName: "quality-report", allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true]) publishHTML([ - reportDir: "helpers-results/types_check", + reportDir: "helpers-results/cl_types_check", reportFiles: "index.html", reportName: "types_check", allowMissing: false, @@ -447,7 +451,7 @@ pipeline { steps { plot([ csvFileName: 'plot-df7f03dc-8146-11ed-a1eb-0242ac120002.csv', - csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_GlobalScore.csv', inclusionFlag: 'OFF', url: '']], + csvSeries: [[ file: 'gitrepo/helpers-results/cl_quality_check/metrics_GlobalScore.csv', inclusionFlag: 'OFF', url: '']], group: 'metrics', title: 'code quality score', style: 'line', @@ -457,7 +461,7 @@ pipeline { yaxisMinimum: '0']) plot([ csvFileName: 'plot-c731cc84-8145-11ed-a1eb-0242ac120002.csv', - csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_rawpercent.csv', inclusionFlag: 'OFF', url: '']], + csvSeries: [[ file: 'gitrepo/helpers-results/cl_quality_check/metrics_rawpercent.csv', inclusionFlag: 'OFF', url: '']], group: 'metrics', title: 'code composition (%)', style: 'stackedArea', @@ -467,7 +471,7 @@ pipeline { yaxisMinimum: '0']) plot([ csvFileName: 'plot-cac33982-8145-11ed-a1eb-0242ac120002.csv', - csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_Statistics.csv', inclusionFlag: 'OFF', url: '']], + csvSeries: [[ file: 'gitrepo/helpers-results/cl_quality_check/metrics_Statistics.csv', inclusionFlag: 'OFF', url: '']], group: 'metrics', title: 'general statistics', style: 'line', @@ -475,7 +479,7 @@ pipeline { numBuilds: '']) plot([ csvFileName: 'plot-cddaced2-8145-11ed-a1eb-0242ac120002.csv', - csvSeries: [[ file: 'gitrepo/helpers-results/quality_check/metrics_MessagesCat.csv', inclusionFlag: 'OFF', url: '']], + csvSeries: [[ file: 'gitrepo/helpers-results/cl_quality_check/metrics_MessagesCat.csv', inclusionFlag: 'OFF', url: '']], group: 'metrics', title: 'quality warnings', style: 'stackedArea', @@ -483,7 +487,7 @@ pipeline { numBuilds: '']) plot([ csvFileName: 'plot-4ceb9ee2-ca78-11ed-afa1-0242ac120002.csv', - csvSeries: [[ file: 'gitrepo/helpers-results/complexity_check/MI.csv', inclusionFlag: 'INCLUDE_BY_STRING',exclusionValues: 'MeanMaintainability', url: '']], + csvSeries: [[ file: 'gitrepo/helpers-results/cl_complexity_check/MI.csv', inclusionFlag: 'INCLUDE_BY_STRING',exclusionValues: 'MeanMaintainability', url: '']], group: 'metrics', title: 'maintainability', style: 'stackedArea', @@ -495,14 +499,14 @@ pipeline { stage("RunUnitTests") { steps { dir("gitrepo") { - sh(". ~/TEST_ENV/bin/activate && python -m helpers --unit-test --coverage-check") + sh(". ~/TEST_ENV/bin/activate && python -m chacha_cicd_helper --unittest --coveragecheck") script { - unit_test_full_name__html=findFiles(glob: "helpers-results/unit_test_full/*.html")[0].getName() + unit_test_full_name__html=findFiles(glob: "helpers-results/cl_unit_test_full/*.html")[0].getName() println unit_test_full_name__html - unit_test_full_name__xml=findFiles(glob: "helpers-results/unit_test_full/*.xml")[0].getName() + unit_test_full_name__xml=findFiles(glob: "helpers-results/cl_unit_test_full/*.xml")[0].getName() println unit_test_full_name__xml - coverage_report_path = "helpers-results/unit_test_coverage/test_coverage.xml" + coverage_report_path = "helpers-results/cl_unit_test_coverage/test_coverage.xml" println GetCoverageValue_lines_valid(coverage_report_path) println GetCoverageValue_lines_covered(coverage_report_path) println GetCoverageValue_line_rate(coverage_report_path) @@ -517,7 +521,7 @@ pipeline { badge_coverage.setColor(getColorScale(full_rate)) //badge_maintainability - records = readCSV file: 'helpers-results/complexity_check/MI.csv' + records = readCSV file: 'helpers-results/cl_complexity_check/MI.csv' maintainability = records[1][1] badge_maintainability.setStatus(maintainability) @@ -532,11 +536,11 @@ pipeline { post { always { dir("gitrepo") { - junit 'helpers-results/unit_test/*.xml' + junit 'helpers-results/cl_unit_test/*.xml' // using cobertura format (= coverage xml format) - publishCoverage adapters: [cobertura(mergeToOneReport: true, path: "helpers-results/unit_test_coverage/test_coverage.xml")] + publishCoverage adapters: [cobertura(mergeToOneReport: true, path: "helpers-results/cl_unit_test_coverage/test_coverage.xml")] publishHTML([ - reportDir: "helpers-results/unit_test_coverage", + reportDir: "helpers-results/cl_unit_test_coverage", reportFiles: "index.html", reportName: "coverage-report-html", allowMissing: false, @@ -544,7 +548,7 @@ pipeline { keepAll: true]) publishHTML([ - reportDir: "helpers-results/unit_test_full", + reportDir: "helpers-results/cl_unit_test_full", reportFiles: unit_test_full_name__html, reportName: "test-reports-full", allowMissing: false, @@ -558,15 +562,14 @@ pipeline { stage("GenDOC") { steps { dir("gitrepo") { - //--doc-gen-pdf - sh(". ~/TEST_ENV/bin/activate && python -m helpers --doc-gen --doc-gen-pdf") + sh(". ~/TEST_ENV/bin/activate && python -m chacha_cicd_helper --docgen --docgenpdf") } } post { always { dir("gitrepo") { publishHTML([ - reportDir: "helpers-results/doc_gen/site", + reportDir: "helpers-results/cl_doc_gen/site", reportFiles: "index.html", reportName: "doc-html", allowMissing: false, @@ -671,11 +674,11 @@ pipeline { | |data = { | "name": "Documentation (pdf)", - | 'attachment': ("${PY_PROJECT_NAME}_${PY_PROJECT_VERSION}_UserManual.pdf", open("helpers-results/doc_gen/site/pdf/manual.pdf", 'rb')), + | 'attachment': ("${PY_PROJECT_NAME}_${PY_PROJECT_VERSION}_UserManual.pdf", open("helpers-results/cl_doc_gen/site/pdf/manual.pdf", 'rb')), |} |GiteaApi.assets.post("${_PROJECT_USER_NAME}","${PY_PROJECT_NAME}",new_release_id,files=data) | - |shutil.make_archive("doc", 'zip', "helpers-results/doc_gen/site") + |shutil.make_archive("doc", 'zip', "helpers-results/cl_doc_gen/site") |reqData={ | "SECRET": "${MKDOCSTOKEN}", | "USER": "${_PROJECT_USER_NAME}", diff --git a/RUN_changelog.launch b/RUN_changelog.launch deleted file mode 100644 index 4dde656..0000000 --- a/RUN_changelog.launch +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/RUN_complexity.launch b/RUN_complexity.launch index 8e17941..364dd2f 100644 --- a/RUN_complexity.launch +++ b/RUN_complexity.launch @@ -2,14 +2,15 @@ - + - + + - + diff --git a/RUN_mkdocs.launch b/RUN_mkdocs.launch index b7c5f92..c7a94eb 100644 --- a/RUN_mkdocs.launch +++ b/RUN_mkdocs.launch @@ -2,17 +2,15 @@ - + - - - - + + - + diff --git a/RUN_quality.launch b/RUN_quality.launch index 66bfecc..9fa6906 100644 --- a/RUN_quality.launch +++ b/RUN_quality.launch @@ -2,14 +2,15 @@ - + - + + - + diff --git a/RUN_unittest.launch b/RUN_unittest.launch index 8ea9138..2d2cdff 100644 --- a/RUN_unittest.launch +++ b/RUN_unittest.launch @@ -2,14 +2,15 @@ - + - + + - + diff --git a/helpers/.gitignore b/helpers/.gitignore deleted file mode 100644 index 9bfc441..0000000 --- a/helpers/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.mypy_cache/ diff --git a/helpers/__init__.py b/helpers/__init__.py deleted file mode 100644 index 725cc2e..0000000 --- a/helpers/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . \ No newline at end of file diff --git a/helpers/__main__.py b/helpers/__main__.py deleted file mode 100644 index c5fb64a..0000000 --- a/helpers/__main__.py +++ /dev/null @@ -1,108 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -from pathlib import Path -import tomli -import argparse -import os -import logging -import sys - -if __package__ == "helpers": - # when calling the module from: > python -m helpers - from .types_check import types_check - from .quality_check import quality_check - from .unit_test import unit_test - from .doc_gen import doc_gen - from .complexity_check import complexity_check -else: - # when calling the __main__.py file (from IDE) - from helpers.types_check import types_check - from helpers.quality_check import quality_check - from helpers.unit_test import unit_test - from helpers.doc_gen import doc_gen - from helpers.complexity_check import complexity_check - -logging.getLogger().setLevel(logging.INFO) - -if __name__ == "__main__": - project_rootdir_path = Path(__file__).parent.parent.absolute() - - with open(project_rootdir_path / "pyproject.toml", mode="rb") as fp: - pyproject = tomli.load(fp) - - parser = argparse.ArgumentParser( - prog="continuous-integration-helper", description="A tiny set of scripts to help continous integration on python" - ) - - parser.add_argument("-tc", "--type-check", dest="typecheck", action="store_true", help="enable static typing check") - - parser.add_argument("-ut", "--unit-test", dest="unittest", action="store_true", help="enable unit-test") - parser.add_argument( - "-cc", "--coverage-check", dest="coveragecheck", action="store_true", help="enable unit-test coverage check (requires unit-test)" - ) - - parser.add_argument("-qc", "--quality-check", dest="qualitycheck", action="store_true", help="enable code quality check") - - parser.add_argument("-dg", "--doc-gen", dest="docgen", action="store_true", help="enable documentation generation using MkDoc") - parser.add_argument( - "-pdf", "--doc-gen-pdf", dest="docgenpdf", action="store_true", help="enable pdf documentation export (requires doc-gen)" - ) - - parser.add_argument("-cpc", "--complexity-check", dest="complexitycheck", action="store_true", help="enable complexity check") - - args = parser.parse_args() - - ################################## - # Dev / Debug forced toogles - # - # -------------------------------- - # - # args.typecheck = True - # args.qualitycheck = True - # args.unittest = True - # args.coveragecheck = True - # args.docgen = True - # args.docgenpdf = True - # args.complexitycheck = True - - helpers = [] - if args.typecheck == True: - helpers.append(types_check) - - if args.unittest == True: - helpers.append(unit_test) - - if args.coveragecheck == True: - if args.unittest == True: - unit_test.enable_coverage_check = True - else: - raise RuntimeError("unit-test is required to enable coverage-check") - - if args.qualitycheck == True: - helpers.append(quality_check) - - if args.docgen == True: - helpers.append(doc_gen) - - if args.docgenpdf == True: - if args.docgen == True: - doc_gen.enable_gen_pdf = True - else: - raise RuntimeError("doc-gen is required to enable doc-gen-pdf") - - if args.complexitycheck == True: - helpers.append(complexity_check) - - for helper in helpers: - helper.set_context(project_rootdir_path, pyproject) - helper.reset_result_dir() - helper.do_job() diff --git a/helpers/complexity_check.py b/helpers/complexity_check.py deleted file mode 100644 index 529e872..0000000 --- a/helpers/complexity_check.py +++ /dev/null @@ -1,70 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -# from pathlib import Path -# import os -import statistics -import csv -from json import loads as JSON_LOADS -from radon.complexity import cc_rank, SCORE -from radon.cli import Config -from radon.cli.harvest import CCHarvester, HCHarvester, MIHarvester - -from .helper_base import helper_withresults_base -from pprint import pprint - - -class complexity_check(helper_withresults_base): - @classmethod - def do_job(cls): - config = Config( - exclude="__init__\.py", - ignore=None, - order=SCORE, - show_closures=False, - no_assert=True, - min="A", - max="F", - multi=False, - ) - - h = MIHarvester([str(_) for _ in sorted((cls.project_rootdir_path / "src").rglob("*.py"))], config).as_json() - res = JSON_LOADS(h) - - with open(cls.get_result_dir() / "MI.json", "w", newline="") as oFile: - oFile.write(h) - - mean = statistics.mean(_["mi"] for _ in res.values()) - - if mean >= 65: - rank = "A+" - elif mean >= 20: - rank = "A" - elif mean >= 10: - rank = "B" - else: - rank = "C" - - RES_MI = {"MeanMaintainability": mean, "MaintainabilityIndex": rank} - with open(cls.get_result_dir() / "MI.csv", "w", newline="") as oFile: - writer = csv.DictWriter(oFile, fieldnames=RES_MI.keys()) - writer.writeheader() - writer.writerow(RES_MI) - - config = Config(exclude=None, ignore=None, order=SCORE, show_closures=False, no_assert=True, min="A", max="F", multi=False) - h = CCHarvester([str(_) for _ in sorted((cls.project_rootdir_path / "src").rglob("*.py"))], config).as_json() - with open(cls.get_result_dir() / "CC.json", "w", newline="") as oFile: - oFile.write(h) - - config = Config(exclude=None, ignore=None, order=SCORE, show_closures=False, no_assert=True, min="A", max="F", by_function=None) - h = HCHarvester([str(_) for _ in sorted((cls.project_rootdir_path / "src").rglob("*.py"))], config).as_json() - with open(cls.get_result_dir() / "HC.json", "w", newline="") as oFile: - oFile.write(h) diff --git a/helpers/doc_gen.py b/helpers/doc_gen.py deleted file mode 100644 index 7c86dd9..0000000 --- a/helpers/doc_gen.py +++ /dev/null @@ -1,98 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -import shutil -import os -import sys -import subprocess -from pathlib import Path -from distutils.dir_util import copy_tree - -import yaml - -try: - from yaml import CLoader as Loader, CDumper as Dumper -except ImportError: - from yaml import Loader, Dumper - -from .helper_base import helper_withresults_base - - -class doc_gen(helper_withresults_base): - enable_gen_pdf: bool = False - - @classmethod - def do_job(cls): - - # create doc root dir - doc_path = cls.project_rootdir_path / "docs" - cls._reset_dir(doc_path) - - site_path = cls.get_result_dir() / "site" - cls._reset_dir(site_path) - - # copy files from main project dir - shutil.copyfile(str(cls.project_rootdir_path / "README.md"), str(doc_path / "README.md")) - shutil.copyfile(str(cls.project_rootdir_path / "LICENSE.md"), str(doc_path / "LICENSE.md")) - - # copy files from static-doc dir - copy_tree(str(cls.project_rootdir_path / "docs-static"), str(doc_path)) - - # generating API doc + nav from python docstrings - reference_path = doc_path / "reference" - cls._reset_dir(reference_path) - - # create one .md per python module - for path in sorted((cls.project_rootdir_path / "src").rglob("*.py")): - module_path = path.relative_to(cls.project_rootdir_path / "src").with_suffix("") - doc_path = path.relative_to(cls.project_rootdir_path / "src").with_suffix(".md") - full_doc_path = Path(reference_path, doc_path) - - parts = list(module_path.parts) - - if parts[-1] in ("__init__", "__main__"): - continue - - cls._create_dir(full_doc_path.parent.resolve()) - with open(full_doc_path, "w+") as fd: - identifier = ".".join(parts) - print("::: " + identifier, file=fd) - - cmdopts = [f"{sys.executable}", "-m", "mkdocs", "-v", "build", "--site-dir", str(site_path), "--clean"] - - # little hack here, to enable / disable pdf generation using own class config - # => reason is mkdocs seems to try loading the plugin even if we disable it, so we need to - # manually process the configuration file. - with open(cls.project_rootdir_path / "mkdocs.yml", "r") as mkdocsCfgFile: - mkdocsCfg = yaml.load(mkdocsCfgFile, Loader=yaml.Loader) - - if "plugins" in mkdocsCfg: - mkdocsCfg["plugins"] = [_ for _ in mkdocsCfg["plugins"] if (not isinstance(_, dict) or "with-pdf" not in _.keys())] - - if cls.enable_gen_pdf == True: - mkdocsCfg["plugins"].append( - { - "with-pdf": { - "cover_subtitle": "User Manual", - "cover_logo": str(cls.project_rootdir_path / "docs-static" / "Library.jpg"), - "verbose": False, - "exclude_pages": ["LICENSE"], - "output_path": str(site_path / "pdf" / "manual.pdf"), - } - } - ) - with open(cls.project_rootdir_path / "mkdocs.yml", "w") as mkdocsCfgFile: - mkdocsCfgFile.write(yaml.dump(mkdocsCfg, Dumper=Dumper, default_flow_style=False, sort_keys=False)) - - print(" !! start doc generation") - res = cls.run_cmd(cmdopts) - print(res.decode()) - print(" !! done") diff --git a/helpers/helper_base.py b/helpers/helper_base.py deleted file mode 100644 index e1bf5db..0000000 --- a/helpers/helper_base.py +++ /dev/null @@ -1,82 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -from abc import ABC, abstractmethod -import os -import shutil -from pathlib import Path -import subprocess - -if TYPE_CHECKING: # Only imports the below statements during type checking - from typing import Union - - -class helper_base(ABC): - project_rootdir_path: Union[Path, None] = None - pyproject: Union[dict, None] = None - current_dir: Union[Path, None] = None - - @classmethod - def set_context(cls, project_rootdir_path: Path, pyproject: dict): - cls.project_rootdir_path = project_rootdir_path - cls.pyproject = pyproject - cls.current_dir = Path(__file__).parent.absolute() - - @classmethod - def get_result_dir(cls): - return None - - @staticmethod - def _create_dir(dirpath: Path): - dirpath = Path(dirpath) - if not os.path.exists(dirpath): - os.makedirs(dirpath) - - @staticmethod - def _reset_dir(dirpath: Path): - dirpath = Path(dirpath) - if os.path.exists(dirpath): - shutil.rmtree(dirpath) - os.makedirs(dirpath) - - @classmethod - def reset_result_dir(cls): - result_dir = cls.get_result_dir() - if result_dir != None: - cls._reset_dir(result_dir) - - @classmethod - @abstractmethod - def do_job(cls): - raise NotImplementedError() - - @classmethod - def run_cmd_(cls, cmdarray): - process = subprocess.run(cmdarray, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, check=True) - return process.stdout - - @classmethod - def run_cmd(cls, cmdarray, silent: bool = False): - p = subprocess.run(cmdarray, capture_output=True) - if not silent: - print(p.stdout.decode()) - print(p.stderr.decode()) - return p.stdout - - -class helper_withresults_base(helper_base): - helper_results_dir: Union[Path, None] = None - - @classmethod - def get_result_dir(cls): - if cls.helper_results_dir == None: - cls.helper_results_dir = cls.__name__ - return Path(__file__).parent.parent.absolute() / "helpers-results" / cls.helper_results_dir diff --git a/helpers/quality_check.py b/helpers/quality_check.py deleted file mode 100644 index c63207b..0000000 --- a/helpers/quality_check.py +++ /dev/null @@ -1,247 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -from contextlib import redirect_stdout -from io import StringIO -import re -import json -from enum import Enum -from contextlib import suppress -import sys -import pandas -import csv -import copy - -from pylint.lint import Run as pylint_Run -import pylint_json2html - -from .helper_base import helper_withresults_base - - -class PyLintMetricNotFound(Warning): - pass - - -class quality_check(helper_withresults_base): - PylintMessageList = dict() - - @classmethod - def GetPylintMessageList(cls): - Messagelist = dict() - regex = r"^:([a-zA-Z-]+) \(([^\)]+)\)" - for line in cls.run_cmd([sys.executable, "-m", "pylint", "--list-msgs"], True).splitlines(): - if res := re.search(regex, line.decode()): - Messagelist[res.group(1)] = res.group(2) - cls.PylintMessageList = Messagelist - - @staticmethod - def TryExtractPYReportMetric(line: str, tag: str): - regex = f"^(?:\|{tag}\s*\|)(\d+)(?=\s*|)" - if res := re.search(regex, line): - return float(res.group(1)) - raise PyLintMetricNotFound() - - @classmethod - def do_job(cls): - print("checking code quality ...") - - cls.GetPylintMessageList() - - RES_all = dict() - with StringIO() as StdOutput: - JsonContent = "" - with redirect_stdout(StdOutput): - pylint_Run( - [ - "--load-plugins=pylint.extensions.mccabe", - "--output-format=json,parseable", - "--disable=invalid-name,too-few-public-methods,too-many-arguments", # ignore - "--ignore=_version.py", - "--reports=y", - "--score=yes", - "--max-line-length=140", - "src." + cls.pyproject["project"]["name"], - ], - exit=False, - ) - - with open(cls.get_result_dir() / "report.json", "w+", encoding="utf-8") as Outfile: - # hacky way of exctracting json + having overall score... - class TScanState(Enum): - TEXT_REPORT = 1 - JSON_REPORT = 2 - OTHER_REPORT_START = 3 - OTHER_REPORT_STATISTICS = 4 - OTHER_REPORT_METRICS = 5 - OTHER_REPORT_DUPLICATION = 6 - OTHER_REPORT_MESSAGES_CAT = 7 - OTHER_REPORT_MESSAGES = 8 - OTHER_REPORT_END = 99 - - RES_all["Statistics"] = dict() - RES_all["RawMetrics"] = dict() - RES_all["RawMetricsPercent"] = dict() - RES_all["Duplication"] = dict() - RES_all["MessagesCat"] = dict() - RES_all["Messages"] = dict() - RES_all["GlobalScore"] = -999 - RES_all["NbAnalysedStatments"] = -999 - RES_all["NbAnalysedLines"] = -999 - - ScanState = TScanState.TEXT_REPORT - for line in StdOutput.getvalue().split("\n"): - print(line) - if ScanState == TScanState.TEXT_REPORT: - # ignoring this part, we need json - if line == "[": - JsonContent += line - ScanState = TScanState.JSON_REPORT - elif line == "[]": - JsonContent += line - ScanState = TScanState.OTHER_REPORT_START - - elif ScanState == TScanState.JSON_REPORT: - JsonContent += line - if line == "]": - ScanState = TScanState.OTHER_REPORT_START - - elif ScanState == TScanState.OTHER_REPORT_START: - if res := re.search(r"^(\d+)(?= statements analysed.)", line): - RES_all["NbAnalysedStatments"] = float(res.group(1)) - if line == "Statistics by type": - ScanState = TScanState.OTHER_REPORT_STATISTICS - - elif ScanState == TScanState.OTHER_REPORT_STATISTICS: - if res := re.search(r"^(\d+)(?= lines have been analyzed)", line): - RES_all["NbAnalysedLines"] = float(res.group(1)) - elif line == "Raw metrics": - ScanState = TScanState.OTHER_REPORT_METRICS - else: - with suppress(PyLintMetricNotFound): - RES_all["Statistics"]["module"] = cls.TryExtractPYReportMetric(line, "module") - with suppress(PyLintMetricNotFound): - RES_all["Statistics"]["class"] = cls.TryExtractPYReportMetric(line, "class") - with suppress(PyLintMetricNotFound): - RES_all["Statistics"]["method"] = cls.TryExtractPYReportMetric(line, "method") - with suppress(PyLintMetricNotFound): - RES_all["Statistics"]["function"] = cls.TryExtractPYReportMetric(line, "function") - - elif ScanState == TScanState.OTHER_REPORT_METRICS: - if line == "Duplication": - RES_all["RawMetricsPercent"]["code"] = RES_all["RawMetrics"]["code"] / RES_all["NbAnalysedLines"] - RES_all["RawMetricsPercent"]["docstring"] = RES_all["RawMetrics"]["docstring"] / RES_all["NbAnalysedLines"] - RES_all["RawMetricsPercent"]["comment"] = RES_all["RawMetrics"]["comment"] / RES_all["NbAnalysedLines"] - RES_all["RawMetricsPercent"]["empty"] = RES_all["RawMetrics"]["empty"] / RES_all["NbAnalysedLines"] - ScanState = TScanState.OTHER_REPORT_DUPLICATION - else: - with suppress(PyLintMetricNotFound): - RES_all["RawMetrics"]["code"] = cls.TryExtractPYReportMetric(line, "code") - with suppress(PyLintMetricNotFound): - RES_all["RawMetrics"]["docstring"] = cls.TryExtractPYReportMetric(line, "docstring") - with suppress(PyLintMetricNotFound): - RES_all["RawMetrics"]["comment"] = cls.TryExtractPYReportMetric(line, "comment") - with suppress(PyLintMetricNotFound): - RES_all["RawMetrics"]["empty"] = cls.TryExtractPYReportMetric(line, "empty") - - elif ScanState == TScanState.OTHER_REPORT_DUPLICATION: - if line == "Messages by category": - ScanState = TScanState.OTHER_REPORT_MESSAGES_CAT - else: - with suppress(PyLintMetricNotFound): - RES_all["Duplication"]["NbDupLines"] = cls.TryExtractPYReportMetric(line, "nb duplicated lines") - with suppress(PyLintMetricNotFound): - RES_all["Duplication"]["PersentDuplicatedLines"] = cls.TryExtractPYReportMetric( - line, "percent duplicated lines" - ) - - elif ScanState == TScanState.OTHER_REPORT_MESSAGES_CAT: - if line == "Messages": - ScanState = TScanState.OTHER_REPORT_MESSAGES - else: - with suppress(PyLintMetricNotFound): - RES_all["MessagesCat"]["Convention"] = cls.TryExtractPYReportMetric(line, "convention") - with suppress(PyLintMetricNotFound): - RES_all["MessagesCat"]["Refactor"] = cls.TryExtractPYReportMetric(line, "refactor") - with suppress(PyLintMetricNotFound): - RES_all["MessagesCat"]["Warning"] = cls.TryExtractPYReportMetric(line, "warning") - with suppress(PyLintMetricNotFound): - RES_all["MessagesCat"]["Error"] = cls.TryExtractPYReportMetric(line, "error") - - elif ScanState == TScanState.OTHER_REPORT_MESSAGES: - # approx match because the number of '-' depend on screen width.. - if line.startswith("--------"): - ScanState = TScanState.OTHER_REPORT_END - else: - for PylintMessage in cls.PylintMessageList.keys(): - with suppress(PyLintMetricNotFound): - RES_all["Messages"][PylintMessage] = cls.TryExtractPYReportMetric(line, PylintMessage) - - elif ScanState == TScanState.OTHER_REPORT_END: - if res := re.search(r"(?<=Your code has been rated at )(\d+(?:\.\d+)?)/10", line): - RES_all["GlobalScore"] = float(res.group(1)) - print(RES_all["GlobalScore"]) - else: - raise RuntimeError("Invalid ScanState") - Outfile.write(JsonContent) - - with open(cls.get_result_dir() / "metrics.json", "w") as json_file: - json.dump(RES_all, json_file) - - # exporting all Data in one csv, unused atm because jenkins seems not able to select columns from csv an keep displaying all... - # => to export a working full csv we need to a 'flat' dict (no more nested dict) - RES_all_trim = copy.deepcopy(RES_all) - del RES_all_trim["Messages"] - flat_RES_all = pandas.json_normalize(RES_all_trim, sep="_").to_dict(orient="records")[0] - - with open(cls.get_result_dir() / "metrics.csv", "w", newline="") as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=flat_RES_all.keys()) - writer.writeheader() - writer.writerow(flat_RES_all) - - # splited csv exports for jenkins plots: RawMetricsPercent - RES_all_percent = RES_all["RawMetricsPercent"] - with open(cls.get_result_dir() / "metrics_rawpercent.csv", "w", newline="") as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=RES_all_percent.keys()) - writer.writeheader() - writer.writerow(RES_all_percent) - - # splited csv exports for jenkins plots: Statistics + Duplication + NbAnalysedStatments + NbAnalysedLines - RES_all_stats = copy.deepcopy(RES_all["Statistics"]) - RES_all_stats["NbDupLines"] = RES_all["Duplication"]["NbDupLines"] - RES_all_stats["PersentDuplicatedLines"] = RES_all["Duplication"]["PersentDuplicatedLines"] - RES_all_stats["NbAnalysedStatments"] = RES_all["NbAnalysedStatments"] - RES_all_stats["NbAnalysedLines"] = RES_all["NbAnalysedLines"] - with open(cls.get_result_dir() / "metrics_Statistics.csv", "w", newline="") as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=RES_all_stats.keys()) - writer.writeheader() - writer.writerow(RES_all_stats) - - # splited csv exports for jenkins plots: Statistics + Duplication - RES_all_MessagesCat = RES_all["MessagesCat"] - with open(cls.get_result_dir() / "metrics_MessagesCat.csv", "w", newline="") as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=RES_all_MessagesCat.keys()) - writer.writeheader() - writer.writerow(RES_all_MessagesCat) - - # splited csv exports for jenkins plots: GlobalScore - RES_GlobalScore = {"GlobalScore": RES_all["GlobalScore"]} - with open(cls.get_result_dir() / "metrics_GlobalScore.csv", "w", newline="") as csv_file: - writer = csv.DictWriter(csv_file, fieldnames=RES_GlobalScore.keys()) - writer.writeheader() - writer.writerow(RES_GlobalScore) - - # converting the report using pylint_json2html (/!\ internal API, but as their is no leading '_' ...) - with open(cls.get_result_dir() / "report.html", "w+", encoding="utf-8") as Outfile: - raw_data = json.loads(JsonContent) - report = pylint_json2html.Report(raw_data) - Outfile.write(report.render()) - - print("Done") diff --git a/helpers/types_check.py b/helpers/types_check.py deleted file mode 100644 index 26b7942..0000000 --- a/helpers/types_check.py +++ /dev/null @@ -1,60 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -from pathlib import Path - -from mypy import api - -from .helper_base import helper_withresults_base - - -class types_check(helper_withresults_base): - JUnitReportName = "junit.xml" - - @classmethod - def do_job(cls): - print("checking code typing ...") - result = api.run( - [ # project path - "-p", - "src." + cls.pyproject["project"]["name"], - # analysis configuration - # "--show-traceback", - "--explicit-package-bases", - # "--strict-equality", - # "--check-untyped-defs", - # reports generation - "--cobertura-xml-report", - str(cls.get_result_dir()), - "--html-report", - str(cls.get_result_dir()), - "--txt-report", - str(cls.get_result_dir()), - "--xml-report", - str(cls.get_result_dir()), - "--junit-xml", - str(cls.get_result_dir()) + "/" + cls.JUnitReportName, - ] - ) - - if result[0]: - print("\nType checking report:\n") - print(result[0]) # stdout - # converting the report using pylint_json2html (/!\ internal API, but as their is no leading '_' ...) - with open(cls.get_result_dir() / "raw_eport.txt", "w+", encoding="utf-8") as Outfile: - Outfile.write(result[0]) - - if result[1]: - print("\nError report:\n") - print(result[1]) # stderr - - print("\nExit status:", result[2]) - print("Done") diff --git a/helpers/unit_test.py b/helpers/unit_test.py deleted file mode 100644 index 4d9d6a3..0000000 --- a/helpers/unit_test.py +++ /dev/null @@ -1,81 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -from __future__ import annotations -from typing import TYPE_CHECKING - -from pathlib import Path -import os -import datetime - -import unittest -import xmlrunner -from junitparser import JUnitXml -from junit2htmlreport import parser as junit2html_parser - -from .helper_base import helper_withresults_base - - -class unit_test(helper_withresults_base): - enable_coverage_check: bool = False - enable_xml_export: bool = True - enable_full_xml_export: bool = True - FullReportName: str = "full_report" - CoverageReportName: str = "test_coverage" - - @classmethod - def do_job(cls): - if cls.enable_coverage_check == True: - import coverage - - # preparing unittest framework - test_loader = unittest.TestLoader() - - if cls.enable_coverage_check == True: - # we start coverage now because module files discovery is part of the coverage measurement - CoverageReportPath = Path(str(cls.get_result_dir()) + "_coverage") - cls._reset_dir(CoverageReportPath) - cov = coverage.Coverage(cover_pylib=False, branch=True, source_pkgs=["src." + cls.pyproject["project"]["name"]]) - cov.start() - - package_tests = test_loader.discover( - start_dir=str(cls.project_rootdir_path / "test"), top_level_dir=str(cls.project_rootdir_path / "test") - ) - if cls.enable_xml_export: - testRunner = xmlrunner.XMLTestRunner(output=str(str(cls.get_result_dir()))) - else: - testRunner = unittest.TextTestRunner() - - # running the test - testRunner.run(package_tests) - - print("Test Finished") - if cls.enable_coverage_check == True: - cov.stop() - cov.save() - cov.html_report(directory=str(CoverageReportPath)) - cov.xml_report(outfile=(CoverageReportPath / f"{cls.CoverageReportName}.xml")) - - # computing results (Only if xml available) - if cls.enable_full_xml_export == True: - print("Full reports generation...") - FullReportPath = Path(str(cls.get_result_dir()) + "_full") - cls._reset_dir(FullReportPath) - - FullJUnitReport = JUnitXml() - for fname in [fname for fname in os.listdir(cls.get_result_dir()) if fname.endswith(".xml")]: - FullJUnitReport += JUnitXml.fromfile(str(cls.get_result_dir() / fname)) - - current_datetime = datetime.datetime.utcnow().strftime("%Y%m%dT%H%M%SZ") - full_report_base_name = f'{cls.pyproject["project"]["name"]}-{cls.FullReportName}-{current_datetime}' - FullJUnitReport.write(str(FullReportPath / f"{full_report_base_name}.xml")) - report = junit2html_parser.Junit(FullReportPath / f"{full_report_base_name}.xml") - html = report.html() - with open(FullReportPath / f"{full_report_base_name}.html", "wb") as outfile: - outfile.write(html.encode("utf-8")) - print("Done") diff --git a/helpers_proxy/__main__.py b/helpers_proxy/__main__.py new file mode 100644 index 0000000..b39dc60 --- /dev/null +++ b/helpers_proxy/__main__.py @@ -0,0 +1,5 @@ +from chacha_cicd_helper.__main__ import fct_main +import sys + +if __name__ == "__main__": + fct_main(sys.argv[1:]) diff --git a/pyproject.toml b/pyproject.toml index d430840..e2b0898 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,12 +57,12 @@ Documentation = "https://chacha.ddns.net/mkdocs-web/chacha/pygamecfg/master/la Tracker = "https://chacha.ddns.net/gitea/chacha/pygamecfg/issues" [project.optional-dependencies] -test = ["junitparser>=2.8","junit2html>=30.1","xmlrunner>=1.7","mypy>=0.99" ] -coverage-check = ["coverage>=7.0"] -complexity-check = ["radon>=5.1"] -quality-check = ["pylint>=2.15","pylint-json2html>=0.4","pandas>=1.5"] -type-check = ["mypy[reports]>=0.99" ] -doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5","mkdocs-material-extensions","mkdocs-pymdownx-material-extras", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0","pymdown-extensions>=9","mkdocs-markdownextradata-plugin","mkdocs-mermaid2-plugin","mkdocs-autorefs"] +test = ["chacha_cicd_helper@git+https://chacha.ddns.net/gitea/chacha/chacha_cicd_helper.git@master"] +coverage-check = ["chacha_cicd_helper@git+https://chacha.ddns.net/gitea/chacha/chacha_cicd_helper.git@master"] +complexity-check = ["chacha_cicd_helper@git+https://chacha.ddns.net/gitea/chacha/chacha_cicd_helper.git@master"] +quality-check = ["chacha_cicd_helper@git+https://chacha.ddns.net/gitea/chacha/chacha_cicd_helper.git@master"] +type-check = ["chacha_cicd_helper@git+https://chacha.ddns.net/gitea/chacha/chacha_cicd_helper.git@master"] +doc-gen = ["chacha_cicd_helper@git+https://chacha.ddns.net/gitea/chacha/chacha_cicd_helper.git@master"] # [project.scripts] # my-script = "my_package.module:function" diff --git a/pyproject.toml.bak b/pyproject.toml.bak deleted file mode 100644 index 1fb8af4..0000000 --- a/pyproject.toml.bak +++ /dev/null @@ -1,68 +0,0 @@ -# pyChaChaDummyProject (c) by chacha -# -# pyChaChaDummyProject is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -[build-system] -requires = ["setuptools>=63", "wheel", "setuptools_scm"] -build-backend = "setuptools.build_meta" - -[tool.setuptools_scm] -version_scheme= "post-release" - -[project] -name = "pygamecfg" -description = "A simple game config tool that provide bash API to read / write game config files (cod, ut ...)" -readme = "README.md" -requires-python = ">=3.9" -keywords = ["chacha","chacha","template","pygamecfg"] -license = { file = "LICENSE.md" } - -authors = [ - {name="chacha",email="1000CHACHA0001@gmail.com"}, -] -maintainers = [ - {name="chacha",email="1000CHACHA0001@gmail.com"}, -] -classifiers = [ - "Development Status :: 4 - Beta", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.9", -] -dependencies = [ - 'importlib-metadata; python_version<"3.9"', - 'packaging', - 'pysimpleini>=0.3.1', - 'typed-argument-parser==1.*' -] -dynamic = ["version"] - -[tool.setuptools] -platforms = ["any"] -include-package-data = true - -[tool.setuptools.packages.find] -where = ["src"] - -[tool.setuptools.package-data] -"pygamecfg.data" = ["*.*"] - -[project.urls] -Homepage = "https://chacha.ddns.net/gitea/chacha/pygamecfg" -Documentation = "https://chacha.ddns.net/mkdocs-web/chacha/pygamecfg/master/latest/" -Tracker = "https://chacha.ddns.net/gitea/chacha/pygamecfg/issues" - -[project.optional-dependencies] -test = ["junitparser>=2.8","junit2html>=30.1","xmlrunner>=1.7","mypy>=0.99" ] -coverage-check = ["coverage>=7.0"] -complexity-check = ["radon>=5.1"] -quality-check = ["pylint>=2.15","pylint-json2html>=0.4","pandas>=1.5"] -type-check = ["mypy[reports]>=0.99" ] -doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5","mkdocs-material-extensions","mkdocs-pymdownx-material-extras", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0","pymdown-extensions>=9","mkdocs-markdownextradata-plugin","mkdocs-mermaid2-plugin","mkdocs-autorefs"] - -# [project.scripts] -# my-script = "my_package.module:function" -