ScriptCollection 3.5.16__py3-none-any.whl → 4.0.78__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ScriptCollection/AnionBuildPlatform.py +206 -0
- ScriptCollection/{UpdateCertificates.py → CertificateUpdater.py} +69 -46
- ScriptCollection/Executables.py +515 -18
- ScriptCollection/GeneralUtilities.py +1272 -873
- ScriptCollection/ImageUpdater.py +648 -0
- ScriptCollection/ProgramRunnerBase.py +10 -10
- ScriptCollection/ProgramRunnerMock.py +2 -0
- ScriptCollection/ProgramRunnerPopen.py +7 -1
- ScriptCollection/ProgramRunnerSudo.py +108 -0
- ScriptCollection/SCLog.py +115 -0
- ScriptCollection/ScriptCollectionCore.py +942 -266
- ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py +95 -0
- ScriptCollection/TFCPS/Docker/__init__.py +0 -0
- ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py +8 -0
- ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py +6 -0
- ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py +7 -0
- ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py +485 -0
- ScriptCollection/TFCPS/DotNet/__init__.py +0 -0
- ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py +130 -0
- ScriptCollection/TFCPS/Flutter/__init__.py +0 -0
- ScriptCollection/TFCPS/Go/TFCPS_CodeUnitSpecific_Go.py +74 -0
- ScriptCollection/TFCPS/Go/__init__.py +0 -0
- ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py +131 -0
- ScriptCollection/TFCPS/NodeJS/__init__.py +0 -0
- ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py +227 -0
- ScriptCollection/TFCPS/Python/__init__.py +0 -0
- ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py +418 -0
- ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py +128 -0
- ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py +136 -0
- ScriptCollection/TFCPS/TFCPS_CreateRelease.py +95 -0
- ScriptCollection/TFCPS/TFCPS_Generic.py +43 -0
- ScriptCollection/TFCPS/TFCPS_MergeToMain.py +122 -0
- ScriptCollection/TFCPS/TFCPS_MergeToStable.py +350 -0
- ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py +47 -0
- ScriptCollection/TFCPS/TFCPS_Tools_General.py +1356 -0
- ScriptCollection/TFCPS/__init__.py +0 -0
- {ScriptCollection-3.5.16.dist-info → scriptcollection-4.0.78.dist-info}/METADATA +23 -22
- scriptcollection-4.0.78.dist-info/RECORD +43 -0
- {ScriptCollection-3.5.16.dist-info → scriptcollection-4.0.78.dist-info}/WHEEL +1 -1
- {ScriptCollection-3.5.16.dist-info → scriptcollection-4.0.78.dist-info}/entry_points.txt +32 -0
- ScriptCollection/ProgramRunnerEpew.py +0 -122
- ScriptCollection/RPStream.py +0 -42
- ScriptCollection/TasksForCommonProjectStructure.py +0 -2625
- ScriptCollection-3.5.16.dist-info/RECORD +0 -16
- {ScriptCollection-3.5.16.dist-info → scriptcollection-4.0.78.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import re
|
|
4
|
+
import zipfile
|
|
5
|
+
from ...GeneralUtilities import GeneralUtilities
|
|
6
|
+
from ...SCLog import LogLevel
|
|
7
|
+
from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
|
|
8
|
+
|
|
9
|
+
class TFCPS_CodeUnitSpecific_Flutter_Functions(TFCPS_CodeUnitSpecific_Base):
|
|
10
|
+
|
|
11
|
+
def __init__(self,current_file:str,verbosity:LogLevel,targetenvironmenttype:str,use_cache:bool,is_pre_merge:bool):
|
|
12
|
+
super().__init__(current_file, verbosity,targetenvironmenttype,use_cache,is_pre_merge)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@GeneralUtilities.check_arguments
|
|
16
|
+
def build(self,package_name:str,targets:list[str]) -> None:
|
|
17
|
+
codeunit_folder = self.get_codeunit_folder()
|
|
18
|
+
codeunit_name = os.path.basename(codeunit_folder)
|
|
19
|
+
src_folder: str = None
|
|
20
|
+
if package_name is None:
|
|
21
|
+
src_folder = codeunit_folder
|
|
22
|
+
else:
|
|
23
|
+
src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder) # TODO replace packagename
|
|
24
|
+
artifacts_folder = os.path.join(codeunit_folder, "Other", "Artifacts")
|
|
25
|
+
|
|
26
|
+
target_names: dict[str, str] = {
|
|
27
|
+
"web": "WebApplication",
|
|
28
|
+
"windows": "Windows",
|
|
29
|
+
"ios": "IOS",
|
|
30
|
+
"appbundle": "Android",
|
|
31
|
+
}
|
|
32
|
+
for target in targets:
|
|
33
|
+
self._protected_sc.log.log(f"Build flutter-codeunit {codeunit_name} for target {target_names[target]}...")
|
|
34
|
+
self._protected_sc.run_with_epew("flutter", f"build {target}", src_folder)
|
|
35
|
+
if target == "web":
|
|
36
|
+
web_relase_folder = os.path.join(src_folder, "build/web")
|
|
37
|
+
web_folder = os.path.join(artifacts_folder, "BuildResult_WebApplication")
|
|
38
|
+
GeneralUtilities.ensure_directory_does_not_exist(web_folder)
|
|
39
|
+
GeneralUtilities.ensure_directory_exists(web_folder)
|
|
40
|
+
GeneralUtilities.copy_content_of_folder(web_relase_folder, web_folder)
|
|
41
|
+
elif target == "windows":
|
|
42
|
+
windows_release_folder = os.path.join(src_folder, "build/windows/x64/runner/Release")
|
|
43
|
+
windows_folder = os.path.join(artifacts_folder, "BuildResult_Windows")
|
|
44
|
+
GeneralUtilities.ensure_directory_does_not_exist(windows_folder)
|
|
45
|
+
GeneralUtilities.ensure_directory_exists(windows_folder)
|
|
46
|
+
GeneralUtilities.copy_content_of_folder(windows_release_folder, windows_folder)
|
|
47
|
+
elif target == "ios":
|
|
48
|
+
raise ValueError("building for ios is not implemented yet")
|
|
49
|
+
elif target == "appbundle":
|
|
50
|
+
aab_folder = os.path.join(artifacts_folder, "BuildResult_AAB")
|
|
51
|
+
GeneralUtilities.ensure_directory_does_not_exist(aab_folder)
|
|
52
|
+
GeneralUtilities.ensure_directory_exists(aab_folder)
|
|
53
|
+
aab_relase_folder = os.path.join(src_folder, "build/app/outputs/bundle/release")
|
|
54
|
+
aab_file_original = self._protected_sc.find_file_by_extension(aab_relase_folder, "aab")
|
|
55
|
+
aab_file = os.path.join(aab_folder, f"{codeunit_name}.aab")
|
|
56
|
+
shutil.copyfile(aab_file_original, aab_file)
|
|
57
|
+
|
|
58
|
+
bundletool = self.tfcps_Tools_General.ensure_androidappbundletool_is_available(None,self.use_cache())
|
|
59
|
+
apk_folder = os.path.join(artifacts_folder, "BuildResult_APK")
|
|
60
|
+
GeneralUtilities.ensure_directory_does_not_exist(apk_folder)
|
|
61
|
+
GeneralUtilities.ensure_directory_exists(apk_folder)
|
|
62
|
+
apks_file = f"{apk_folder}/{codeunit_name}.apks"
|
|
63
|
+
self._protected_sc.run_program("java", f"-jar {bundletool} build-apks --bundle={aab_file} --output={apks_file} --mode=universal", aab_relase_folder)
|
|
64
|
+
with zipfile.ZipFile(apks_file, "r") as zip_ref:
|
|
65
|
+
zip_ref.extract("universal.apk", apk_folder)
|
|
66
|
+
GeneralUtilities.ensure_file_does_not_exist(apks_file)
|
|
67
|
+
os.rename(f"{apk_folder}/universal.apk", f"{apk_folder}/{codeunit_name}.apk")
|
|
68
|
+
else:
|
|
69
|
+
raise ValueError(f"Not supported target: {target}")
|
|
70
|
+
self.copy_source_files_to_output_directory()
|
|
71
|
+
|
|
72
|
+
@GeneralUtilities.check_arguments
|
|
73
|
+
def linting(self) -> None:
|
|
74
|
+
pass#TODO
|
|
75
|
+
|
|
76
|
+
@GeneralUtilities.check_arguments
|
|
77
|
+
def do_common_tasks(self,current_codeunit_version:str )-> None:
|
|
78
|
+
self.do_common_tasks_base(current_codeunit_version)
|
|
79
|
+
|
|
80
|
+
@GeneralUtilities.check_arguments
|
|
81
|
+
def generate_reference(self) -> None:
|
|
82
|
+
self.generate_reference_using_docfx()
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@GeneralUtilities.check_arguments
|
|
86
|
+
def run_testcases(self,package_name:str) -> None:
|
|
87
|
+
codeunit_folder = self.get_codeunit_folder()
|
|
88
|
+
repository_folder = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
|
|
89
|
+
codeunit_name = os.path.basename(codeunit_folder)
|
|
90
|
+
src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder)
|
|
91
|
+
|
|
92
|
+
self._protected_sc.run_with_epew("flutter", "test --coverage", src_folder)
|
|
93
|
+
test_coverage_folder_relative = "Other/Artifacts/TestCoverage"
|
|
94
|
+
test_coverage_folder = GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
|
|
95
|
+
GeneralUtilities.ensure_directory_exists(test_coverage_folder)
|
|
96
|
+
coverage_file_relative = f"{test_coverage_folder_relative}/TestCoverage.xml"
|
|
97
|
+
coverage_file = GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
|
|
98
|
+
self._protected_sc.run_with_epew("lcov_cobertura", f"coverage/lcov.info --base-dir . --excludes test --output ../{coverage_file_relative} --demangle", src_folder)
|
|
99
|
+
|
|
100
|
+
# format correctly
|
|
101
|
+
content = GeneralUtilities.read_text_from_file(coverage_file)
|
|
102
|
+
content = re.sub('<![^<]+>', '', content)
|
|
103
|
+
content = re.sub('\\\\', '/', content)
|
|
104
|
+
content = re.sub('\\ name=\\"lib\\"', '', content)
|
|
105
|
+
content = re.sub('\\ filename=\\"lib/', f' filename="{package_name}/lib/', content)
|
|
106
|
+
GeneralUtilities.write_text_to_file(coverage_file, content)
|
|
107
|
+
self.tfcps_Tools_General.merge_packages(coverage_file, self.get_codeunit_name())
|
|
108
|
+
self.tfcps_Tools_General.calculate_entire_line_rate(coverage_file)
|
|
109
|
+
self.run_testcases_common_post_task(repository_folder, codeunit_name, True, self.get_target_environment_type())
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def get_dependencies(self)->dict[str,set[str]]:
|
|
113
|
+
return []#TODO
|
|
114
|
+
|
|
115
|
+
@GeneralUtilities.check_arguments
|
|
116
|
+
def get_available_versions(self,dependencyname:str)->list[str]:
|
|
117
|
+
return []#TODO
|
|
118
|
+
|
|
119
|
+
def set_dependency_version(self,name:str,new_version:str)->None:
|
|
120
|
+
raise ValueError(f"Operation is not implemented.")
|
|
121
|
+
|
|
122
|
+
class TFCPS_CodeUnitSpecific_Flutter_CLI:
|
|
123
|
+
|
|
124
|
+
@staticmethod
|
|
125
|
+
def parse(file:str)->TFCPS_CodeUnitSpecific_Flutter_Functions:
|
|
126
|
+
parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
|
|
127
|
+
#add custom parameter if desired
|
|
128
|
+
args=parser.parse_args()
|
|
129
|
+
result:TFCPS_CodeUnitSpecific_Flutter_Functions=TFCPS_CodeUnitSpecific_Flutter_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
|
|
130
|
+
return result
|
|
File without changes
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from lxml import etree
|
|
3
|
+
from ...GeneralUtilities import GeneralUtilities
|
|
4
|
+
from ...ScriptCollectionCore import ScriptCollectionCore
|
|
5
|
+
from ...SCLog import LogLevel
|
|
6
|
+
from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
|
|
7
|
+
|
|
8
|
+
class TFCPS_CodeUnitSpecific_Go_Functions(TFCPS_CodeUnitSpecific_Base):
|
|
9
|
+
|
|
10
|
+
def __init__(self,current_file:str,verbosity:LogLevel,targetenvironmenttype:str,use_cache:bool,is_pre_merge:bool):
|
|
11
|
+
super().__init__(current_file, verbosity,targetenvironmenttype,use_cache,is_pre_merge)
|
|
12
|
+
|
|
13
|
+
@GeneralUtilities.check_arguments
|
|
14
|
+
def build(self) -> None:
|
|
15
|
+
#TODO
|
|
16
|
+
self.__generate_sbom_for_go_image()
|
|
17
|
+
|
|
18
|
+
@GeneralUtilities.check_arguments
|
|
19
|
+
def __generate_sbom_for_go_image(self) -> None:
|
|
20
|
+
pass#TODO
|
|
21
|
+
|
|
22
|
+
@GeneralUtilities.check_arguments
|
|
23
|
+
def linting(self) -> None:
|
|
24
|
+
pass#TODO
|
|
25
|
+
|
|
26
|
+
@GeneralUtilities.check_arguments
|
|
27
|
+
def __update_coverage_file(self,coverage_file:str) -> None:
|
|
28
|
+
tree = etree.parse(coverage_file)
|
|
29
|
+
root = tree.getroot()
|
|
30
|
+
for package in root.findall(".//package"):
|
|
31
|
+
package.set("name",self.get_codeunit_name())
|
|
32
|
+
for cls in root.findall(".//class"):
|
|
33
|
+
filename = cls.get("filename")
|
|
34
|
+
if filename:
|
|
35
|
+
cls.set("filename", f"./{filename}")
|
|
36
|
+
cls.set("name",str(filename).rsplit("/", 1)[-1])
|
|
37
|
+
tree.write(coverage_file, encoding="utf-8", xml_declaration=True, pretty_print=True)
|
|
38
|
+
|
|
39
|
+
@GeneralUtilities.check_arguments
|
|
40
|
+
def run_testcases(self) -> None:
|
|
41
|
+
test_coverage_folder = os.path.join(self.get_codeunit_folder(), "Other", "Artifacts", "TestCoverage").replace("\\", "/")
|
|
42
|
+
GeneralUtilities.ensure_directory_exists(test_coverage_folder)
|
|
43
|
+
src_folder = GeneralUtilities.resolve_relative_path(self.get_codeunit_name(), self.get_codeunit_folder())
|
|
44
|
+
sc: ScriptCollectionCore = ScriptCollectionCore()
|
|
45
|
+
sc.run_program_argsasarray("go", ["install", "github.com/t-yuki/gocover-cobertura@latest"], src_folder)
|
|
46
|
+
sc.run_program_argsasarray("go", ["test", "-coverprofile=coverage.out", "./..."], src_folder)
|
|
47
|
+
coverage_file:str=f"{test_coverage_folder}/TestCoverage.xml"
|
|
48
|
+
sc.run_program_argsasarray("sh", ["-c", f"gocover-cobertura < coverage.out > {coverage_file}"], src_folder)
|
|
49
|
+
self.__update_coverage_file(coverage_file)
|
|
50
|
+
self.run_testcases_common_post_task(self.get_repository_folder(),self.get_codeunit_name(),True,self.get_type_environment_type())
|
|
51
|
+
|
|
52
|
+
def get_dependencies(self)->dict[str,set[str]]:
|
|
53
|
+
return []#TODO
|
|
54
|
+
|
|
55
|
+
@GeneralUtilities.check_arguments
|
|
56
|
+
def get_available_versions(self,dependencyname:str)->list[str]:
|
|
57
|
+
return []#TODO
|
|
58
|
+
|
|
59
|
+
def set_dependency_version(self,name:str,new_version:str)->None:
|
|
60
|
+
raise ValueError(f"Operation is not implemented.")
|
|
61
|
+
|
|
62
|
+
class TFCPS_CodeUnitSpecific_Go_CLI:
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def parse(file:str)->TFCPS_CodeUnitSpecific_Go_Functions:
|
|
66
|
+
parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
|
|
67
|
+
#add custom parameter if desired
|
|
68
|
+
args=parser.parse_args()
|
|
69
|
+
result:TFCPS_CodeUnitSpecific_Go_Functions=TFCPS_CodeUnitSpecific_Go_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
|
|
70
|
+
return result
|
|
71
|
+
|
|
72
|
+
def run_testcases():
|
|
73
|
+
t :TFCPS_CodeUnitSpecific_Go_Functions= TFCPS_CodeUnitSpecific_Go_CLI().parse(__file__)
|
|
74
|
+
t.run_testcases()
|
|
File without changes
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from lxml import etree
|
|
4
|
+
from ...GeneralUtilities import GeneralUtilities
|
|
5
|
+
from ...SCLog import LogLevel
|
|
6
|
+
from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
|
|
7
|
+
|
|
8
|
+
class TFCPS_CodeUnitSpecific_NodeJS_Functions(TFCPS_CodeUnitSpecific_Base):
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def __init__(self,current_file:str,verbosity:LogLevel,targetenvironmenttype:str,use_cache:bool,is_pre_merge:bool):
|
|
12
|
+
super().__init__(current_file, verbosity,targetenvironmenttype,use_cache,is_pre_merge)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@GeneralUtilities.check_arguments
|
|
16
|
+
def build(self) -> None:
|
|
17
|
+
self._protected_sc.run_with_epew("npm", "run build", self.get_codeunit_folder(),print_live_output=self._protected_sc.log.loglevel==LogLevel.Diagnostic,encode_argument_in_base64=True)
|
|
18
|
+
self.standardized_tasks_build_bom_for_node_project()
|
|
19
|
+
self.copy_source_files_to_output_directory()
|
|
20
|
+
|
|
21
|
+
@GeneralUtilities.check_arguments
|
|
22
|
+
def linting(self) -> None:
|
|
23
|
+
self._protected_sc.run_with_epew("npm", "run lint", self.get_codeunit_folder(),print_live_output=self._protected_sc.log.loglevel==LogLevel.Diagnostic,encode_argument_in_base64=True)
|
|
24
|
+
|
|
25
|
+
@GeneralUtilities.check_arguments
|
|
26
|
+
def do_common_tasks(self,current_codeunit_version:str)-> None:
|
|
27
|
+
codeunit_version = current_codeunit_version
|
|
28
|
+
codeunit_folder = self.get_codeunit_folder()
|
|
29
|
+
self.do_common_tasks_base(current_codeunit_version)
|
|
30
|
+
self.tfcps_Tools_General.replace_version_in_packagejson_file(GeneralUtilities.resolve_relative_path("./package.json", codeunit_folder), codeunit_version)
|
|
31
|
+
self.tfcps_Tools_General.do_npm_install(codeunit_folder, True,self.use_cache())
|
|
32
|
+
#if generateAPIClientBase.generate_api_client():
|
|
33
|
+
# generateAPIClientGenerate:GenerateAPIClientGenerate=generateAPIClientBase
|
|
34
|
+
# self.tfcps_Tools_General.generate_api_client_from_dependent_codeunit_in_angular(codeunit_folder, generateAPIClientGenerate.name_of_api_providing_codeunit,generateAPIClientGenerate.generate_api_client)
|
|
35
|
+
|
|
36
|
+
@GeneralUtilities.check_arguments
|
|
37
|
+
def generate_reference(self) -> None:
|
|
38
|
+
self.generate_reference_using_docfx()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@GeneralUtilities.check_arguments
|
|
42
|
+
def run_testcases(self) -> None:
|
|
43
|
+
# prepare
|
|
44
|
+
codeunit_name: str =self.get_codeunit_name()
|
|
45
|
+
|
|
46
|
+
codeunit_folder =self.get_codeunit_folder()
|
|
47
|
+
repository_folder = os.path.dirname(codeunit_folder)
|
|
48
|
+
|
|
49
|
+
# run testcases
|
|
50
|
+
self._protected_sc.run_with_epew("npm", f"run test-{self.get_target_environment_type()}", self.get_codeunit_folder(),print_live_output=self._protected_sc.log.loglevel==LogLevel.Diagnostic,encode_argument_in_base64=True)
|
|
51
|
+
|
|
52
|
+
# rename file
|
|
53
|
+
coverage_folder = os.path.join(codeunit_folder, "Other", "Artifacts", "TestCoverage")
|
|
54
|
+
target_file = os.path.join(coverage_folder, "TestCoverage.xml")
|
|
55
|
+
GeneralUtilities.ensure_file_does_not_exist(target_file)
|
|
56
|
+
os.rename(os.path.join(coverage_folder, "cobertura-coverage.xml"), target_file)
|
|
57
|
+
self.__rename_packagename_in_coverage_file(target_file, codeunit_name)
|
|
58
|
+
|
|
59
|
+
# adapt backslashs to slashs
|
|
60
|
+
content = GeneralUtilities.read_text_from_file(target_file)
|
|
61
|
+
content = re.sub('\\\\', '/', content)
|
|
62
|
+
GeneralUtilities.write_text_to_file(target_file, content)
|
|
63
|
+
|
|
64
|
+
# aggregate packages in testcoverage-file
|
|
65
|
+
roottree: etree._ElementTree = etree.parse(target_file)
|
|
66
|
+
existing_classes = list(roottree.xpath('//coverage/packages/package/classes/class'))
|
|
67
|
+
|
|
68
|
+
old_packages_list = roottree.xpath('//coverage/packages/package')
|
|
69
|
+
for package in old_packages_list:
|
|
70
|
+
package.getparent().remove(package)
|
|
71
|
+
|
|
72
|
+
root = roottree.getroot()
|
|
73
|
+
packages_element = root.find("packages")
|
|
74
|
+
package_element = etree.SubElement(packages_element, "package")
|
|
75
|
+
package_element.attrib['name'] = codeunit_name
|
|
76
|
+
package_element.attrib['lines-valid'] = root.attrib["lines-valid"]
|
|
77
|
+
package_element.attrib['lines-covered'] = root.attrib["lines-covered"]
|
|
78
|
+
package_element.attrib['line-rate'] = root.attrib["line-rate"]
|
|
79
|
+
package_element.attrib['branches-valid'] = root.attrib["branches-valid"]
|
|
80
|
+
package_element.attrib['branches-covered'] = root.attrib["branches-covered"]
|
|
81
|
+
package_element.attrib['branch-rate'] = root.attrib["branch-rate"]
|
|
82
|
+
package_element.attrib['timestamp'] = root.attrib["timestamp"]
|
|
83
|
+
package_element.attrib['complexity'] = root.attrib["complexity"]
|
|
84
|
+
|
|
85
|
+
classes_element = etree.SubElement(package_element, "classes")
|
|
86
|
+
|
|
87
|
+
for existing_class in existing_classes:
|
|
88
|
+
classes_element.append(existing_class)
|
|
89
|
+
|
|
90
|
+
result = etree.tostring(roottree, pretty_print=True).decode("utf-8")
|
|
91
|
+
GeneralUtilities.write_text_to_file(target_file, result)
|
|
92
|
+
|
|
93
|
+
# post tasks
|
|
94
|
+
self.run_testcases_common_post_task(repository_folder, codeunit_name, True, self.get_target_environment_type())
|
|
95
|
+
|
|
96
|
+
@GeneralUtilities.check_arguments
|
|
97
|
+
def __rename_packagename_in_coverage_file(self, file: str, codeunit_name: str) -> None:
|
|
98
|
+
root: etree._ElementTree = etree.parse(file)
|
|
99
|
+
packages = root.xpath('//coverage/packages/package')
|
|
100
|
+
for package in packages:
|
|
101
|
+
package.attrib['name'] = codeunit_name
|
|
102
|
+
result = etree.tostring(root).decode("utf-8")
|
|
103
|
+
GeneralUtilities.write_text_to_file(file, result)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@GeneralUtilities.check_arguments
|
|
107
|
+
def standardized_tasks_build_bom_for_node_project(self) -> None:
|
|
108
|
+
relative_path_to_bom_file = f"Other/Artifacts/BOM/{os.path.basename(self.get_codeunit_folder())}.{self.tfcps_Tools_General.get_version_of_codeunit(self.get_codeunit_file())}.sbom.xml"
|
|
109
|
+
self._protected_sc.run_with_epew("cyclonedx-npm", f"--output-format xml --output-file {relative_path_to_bom_file}", self.get_codeunit_folder(),print_live_output=self._protected_sc.log.loglevel==LogLevel.Diagnostic,encode_argument_in_base64=True)
|
|
110
|
+
self._protected_sc.format_xml_file(self.get_codeunit_folder()+"/"+relative_path_to_bom_file)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_dependencies(self)->dict[str,set[str]]:
|
|
114
|
+
return []#TODO
|
|
115
|
+
|
|
116
|
+
@GeneralUtilities.check_arguments
|
|
117
|
+
def get_available_versions(self,dependencyname:str)->list[str]:
|
|
118
|
+
return []#TODO
|
|
119
|
+
|
|
120
|
+
def set_dependency_version(self,name:str,new_version:str)->None:
|
|
121
|
+
raise ValueError(f"Operation is not implemented.")
|
|
122
|
+
|
|
123
|
+
class TFCPS_CodeUnitSpecific_NodeJS_CLI:
|
|
124
|
+
|
|
125
|
+
@staticmethod
|
|
126
|
+
def parse(file:str)->TFCPS_CodeUnitSpecific_NodeJS_Functions:
|
|
127
|
+
parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
|
|
128
|
+
#add custom parameter if desired
|
|
129
|
+
args=parser.parse_args()
|
|
130
|
+
result:TFCPS_CodeUnitSpecific_NodeJS_Functions=TFCPS_CodeUnitSpecific_NodeJS_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
|
|
131
|
+
return result
|
|
File without changes
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from ...GeneralUtilities import GeneralUtilities,Dependency
|
|
4
|
+
from ...SCLog import LogLevel
|
|
5
|
+
from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
|
|
6
|
+
|
|
7
|
+
class TFCPS_CodeUnitSpecific_Python_Functions(TFCPS_CodeUnitSpecific_Base):
|
|
8
|
+
|
|
9
|
+
def __init__(self,current_file:str,verbosity:LogLevel,targetenvironmenttype:str,use_cache:bool,is_pre_merge:bool):
|
|
10
|
+
super().__init__(current_file, verbosity,targetenvironmenttype,use_cache,is_pre_merge)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@GeneralUtilities.check_arguments
|
|
14
|
+
def build(self) -> None:
|
|
15
|
+
codeunit_folder = self.get_codeunit_folder()
|
|
16
|
+
target_directory = GeneralUtilities.resolve_relative_path("../Artifacts/BuildResult_Wheel", os.path.join(self.get_artifacts_folder()))
|
|
17
|
+
GeneralUtilities.ensure_directory_exists(target_directory)
|
|
18
|
+
self._protected_sc.run_program("python", f"-m build --wheel --outdir {target_directory}", codeunit_folder)
|
|
19
|
+
self.generate_bom_for_python_project( )
|
|
20
|
+
self.copy_source_files_to_output_directory()
|
|
21
|
+
|
|
22
|
+
@GeneralUtilities.check_arguments
|
|
23
|
+
def generate_bom_for_python_project(self) -> None:
|
|
24
|
+
codeunit_folder: str=self.get_codeunit_folder()
|
|
25
|
+
codeunitname: str=self.get_codeunit_name()
|
|
26
|
+
repository_folder = os.path.dirname(codeunit_folder)
|
|
27
|
+
|
|
28
|
+
codeunitversion = self.tfcps_Tools_General.get_version_of_codeunit(self.get_codeunit_file())
|
|
29
|
+
bom_folder = "Other/Artifacts/BOM"
|
|
30
|
+
bom_folder_full = os.path.join(codeunit_folder, bom_folder)
|
|
31
|
+
GeneralUtilities.ensure_directory_exists(bom_folder_full)
|
|
32
|
+
if not os.path.isfile(os.path.join(codeunit_folder, "requirements.txt")):
|
|
33
|
+
raise ValueError(f"Codeunit {codeunitname} does not have a 'requirements.txt'-file.")
|
|
34
|
+
# TODO check that all values from setup.cfg are contained in requirements.txt
|
|
35
|
+
result = self._protected_sc.run_program("cyclonedx-py", "requirements", codeunit_folder)
|
|
36
|
+
bom_file_relative_json = f"{bom_folder}/{codeunitname}.{codeunitversion}.bom.json"
|
|
37
|
+
bom_file_relative_xml = f"{bom_folder}/{codeunitname}.{codeunitversion}.bom.xml"
|
|
38
|
+
bom_file_json = os.path.join(codeunit_folder, bom_file_relative_json)
|
|
39
|
+
bom_file_xml = os.path.join(codeunit_folder, bom_file_relative_xml)
|
|
40
|
+
|
|
41
|
+
GeneralUtilities.ensure_file_exists(bom_file_json)
|
|
42
|
+
GeneralUtilities.write_text_to_file(bom_file_json, result[1])
|
|
43
|
+
cyclonedx_exe=self.tfcps_Tools_General.ensure_cyclonedxcli_is_available(repository_folder,not self.use_cache())
|
|
44
|
+
self._protected_sc.run_program(cyclonedx_exe, f"convert --input-file ./{codeunitname}/{bom_file_relative_json} --input-format json --output-file ./{codeunitname}/{bom_file_relative_xml} --output-format xml", repository_folder)
|
|
45
|
+
self._protected_sc.format_xml_file(bom_file_xml)
|
|
46
|
+
GeneralUtilities.ensure_file_does_not_exist(bom_file_json)
|
|
47
|
+
|
|
48
|
+
@GeneralUtilities.check_arguments
|
|
49
|
+
def linting(self) -> None:
|
|
50
|
+
codeunitname: str = self.get_codeunit_name()
|
|
51
|
+
|
|
52
|
+
repository_folder: str = self.get_repository_folder()
|
|
53
|
+
errors_found = False
|
|
54
|
+
self._protected_sc.log.log(f"Check for linting-issues in codeunit {codeunitname}.")
|
|
55
|
+
src_folder = os.path.join(repository_folder, codeunitname, codeunitname)
|
|
56
|
+
tests_folder = src_folder+"Tests"
|
|
57
|
+
# TODO check if there are errors in sarif-file
|
|
58
|
+
for file in GeneralUtilities.get_all_files_of_folder(src_folder)+GeneralUtilities.get_all_files_of_folder(tests_folder):
|
|
59
|
+
relative_file_path_in_repository = os.path.relpath(file, repository_folder)
|
|
60
|
+
if file.endswith(".py") and os.path.getsize(file) > 0 and not self._protected_sc.file_is_git_ignored(relative_file_path_in_repository, repository_folder):
|
|
61
|
+
self._protected_sc.log.log(f"Check for linting-issues in {os.path.relpath(file, os.path.join(repository_folder, codeunitname))}.")
|
|
62
|
+
linting_result = self._protected_sc.python_file_has_errors(file, repository_folder)
|
|
63
|
+
if (linting_result[0]):
|
|
64
|
+
errors_found = True
|
|
65
|
+
for error in linting_result[1]:
|
|
66
|
+
self._protected_sc.log.log(error, LogLevel.Warning)
|
|
67
|
+
if errors_found:
|
|
68
|
+
raise ValueError("Linting-issues occurred.")
|
|
69
|
+
else:
|
|
70
|
+
self._protected_sc.log.log("No linting-issues found.")
|
|
71
|
+
|
|
72
|
+
@GeneralUtilities.check_arguments
|
|
73
|
+
def do_common_tasks(self,current_codeunit_version:str )-> None:
|
|
74
|
+
self.do_common_tasks_base(current_codeunit_version)
|
|
75
|
+
codeunitname =self.get_codeunit_name()
|
|
76
|
+
codeunit_version = self.tfcps_Tools_General.get_version_of_project(self.get_repository_folder())
|
|
77
|
+
self._protected_sc.replace_version_in_ini_file(GeneralUtilities.resolve_relative_path("./setup.cfg", self.get_codeunit_folder()), codeunit_version)
|
|
78
|
+
self._protected_sc.replace_version_in_python_file(GeneralUtilities.resolve_relative_path(f"./{codeunitname}/{codeunitname}Core.py", self.get_codeunit_folder()), codeunit_version)
|
|
79
|
+
|
|
80
|
+
@GeneralUtilities.check_arguments
|
|
81
|
+
def generate_reference(self) -> None:
|
|
82
|
+
self.generate_reference_using_docfx()
|
|
83
|
+
|
|
84
|
+
@GeneralUtilities.check_arguments
|
|
85
|
+
def run_testcases(self) -> None:
|
|
86
|
+
codeunitname: str =self.get_codeunit_name()
|
|
87
|
+
repository_folder: str = self.get_repository_folder()
|
|
88
|
+
codeunit_folder = os.path.join(repository_folder, codeunitname)
|
|
89
|
+
self._protected_sc.run_program("coverage", f"run -m pytest -s ./{codeunitname}Tests", codeunit_folder)
|
|
90
|
+
self._protected_sc.run_program("coverage", "xml", codeunit_folder)
|
|
91
|
+
coveragefolder = os.path.join(repository_folder, codeunitname, "Other/Artifacts/TestCoverage")
|
|
92
|
+
GeneralUtilities.ensure_directory_exists(coveragefolder)
|
|
93
|
+
coveragefile = os.path.join(coveragefolder, "TestCoverage.xml")
|
|
94
|
+
GeneralUtilities.ensure_file_does_not_exist(coveragefile)
|
|
95
|
+
os.rename(os.path.join(repository_folder, codeunitname, "coverage.xml"), coveragefile)
|
|
96
|
+
self.tfcps_Tools_General.merge_packages(coveragefile,codeunitname)
|
|
97
|
+
self.run_testcases_common_post_task(repository_folder, codeunitname, True, self.get_type_environment_type())
|
|
98
|
+
|
|
99
|
+
def get_dependencies(self)->dict[str,set[str]]:
|
|
100
|
+
return GeneralUtilities.merge_dependency_lists([
|
|
101
|
+
self.get_dependencies_from_setupcfg(),
|
|
102
|
+
self.get_dependencies_from_requirementstxt(),
|
|
103
|
+
self.get_dependencies_from_otherrequirementstxt()
|
|
104
|
+
])
|
|
105
|
+
|
|
106
|
+
def get_dependencies_from_setupcfg(self)->list[Dependency]:
|
|
107
|
+
setupcfg_file=os.path.join(self.get_codeunit_folder(),"setup.cfg")
|
|
108
|
+
lines = GeneralUtilities.read_lines_from_file(setupcfg_file)
|
|
109
|
+
result:list[Dependency]=[]
|
|
110
|
+
is_in_dependency_section=False
|
|
111
|
+
for line in lines:
|
|
112
|
+
if line=="install_requires =":
|
|
113
|
+
is_in_dependency_section=True
|
|
114
|
+
elif line.startswith(" "):
|
|
115
|
+
if is_in_dependency_section:
|
|
116
|
+
match = re.match(r"^\s*([A-Za-z0-9_\-]+)\s*([<>=!~]+)?\s*(.*)?$", line)
|
|
117
|
+
if match:
|
|
118
|
+
dep_name = match.group(1)
|
|
119
|
+
dep_operator = match.group(2) or None#pylint:disable=unused-variable
|
|
120
|
+
dep_version = match.group(3) or None
|
|
121
|
+
dep=Dependency(dep_name,dep_version)
|
|
122
|
+
result.append(dep)
|
|
123
|
+
else:
|
|
124
|
+
raise ValueError(f"Unparsable dependency-definition-line: \"{line}\"")
|
|
125
|
+
else:
|
|
126
|
+
is_in_dependency_section=False
|
|
127
|
+
return result
|
|
128
|
+
|
|
129
|
+
def get_dependencies_from_requirementstxt(self)->list[Dependency]:
|
|
130
|
+
return self.get_dependencies_from_requirementsfile(os.path.join(self.get_codeunit_folder(),"requirements.txt"))
|
|
131
|
+
|
|
132
|
+
def get_dependencies_from_otherrequirementstxt(self)->list[Dependency]:
|
|
133
|
+
rfile=os.path.join(self.get_codeunit_folder(),"Other","requirements.txt")
|
|
134
|
+
if os.path.isfile(rfile):
|
|
135
|
+
return self.get_dependencies_from_requirementsfile(rfile)
|
|
136
|
+
else:
|
|
137
|
+
return []
|
|
138
|
+
|
|
139
|
+
def get_dependencies_from_requirementsfile(self,file:str)->list[Dependency]:
|
|
140
|
+
lines = GeneralUtilities.read_lines_from_file(file)
|
|
141
|
+
result:list[Dependency]=[]
|
|
142
|
+
for line in lines:
|
|
143
|
+
match = re.match(r"^([A-Za-z0-9_\-]+)\s*([<>=!~]+)?\s*(.*)?$", line)
|
|
144
|
+
if match:
|
|
145
|
+
dep_name = match.group(1)
|
|
146
|
+
dep_operator = match.group(2) or None#pylint:disable=unused-variable
|
|
147
|
+
dep_version = match.group(3) or None
|
|
148
|
+
dep=Dependency(dep_name,dep_version)
|
|
149
|
+
result.append(dep)
|
|
150
|
+
|
|
151
|
+
return result
|
|
152
|
+
|
|
153
|
+
@GeneralUtilities.check_arguments
|
|
154
|
+
def get_available_versions(self,dependencyname:str)->list[str]:
|
|
155
|
+
result=self._protected_sc.run_program("pip3",f"index versions {dependencyname}")
|
|
156
|
+
available_versions_line:str=[line for line in GeneralUtilities.string_to_lines(result[1]) if line.startswith("Available versions: ")][0]
|
|
157
|
+
available_versions=[version_str.strip() for version_str in available_versions_line[len("Available versions: "):].split(",")]
|
|
158
|
+
result=[]
|
|
159
|
+
for v in available_versions:
|
|
160
|
+
if re.match(r"^(\d+).(\d+).(\d+)$", v) is not None:
|
|
161
|
+
result.append(v)
|
|
162
|
+
elif re.match(r"^(\d+).(\d+)$", v) is not None:
|
|
163
|
+
result.append(v+".0")
|
|
164
|
+
elif re.match(r"^(\d+)$", v) is not None:
|
|
165
|
+
result.append(v+".0.0")
|
|
166
|
+
return result
|
|
167
|
+
|
|
168
|
+
def set_dependency_version(self,name:str,new_version:str)->None:
|
|
169
|
+
self.__set_dependency_version_in_setupcfg(name,new_version)
|
|
170
|
+
self.__set_dependency_version_in_requirementstxt(name,new_version)
|
|
171
|
+
self.__set_dependency_version_in_otherrequirementstxt(name,new_version)
|
|
172
|
+
|
|
173
|
+
def __set_dependency_version_in_setupcfg(self,name:str,new_version:str)->None:
|
|
174
|
+
setupcfg_file=os.path.join(self.get_codeunit_folder(),"setup.cfg")
|
|
175
|
+
lines=GeneralUtilities.read_lines_from_file(setupcfg_file)
|
|
176
|
+
new_lines:list[str]=[]
|
|
177
|
+
for line in lines:
|
|
178
|
+
match = re.match("^(\\s*)("+re.escape(name)+")\\s*([<>=!~]+)?\\s*(.*)?$", line)
|
|
179
|
+
if match:
|
|
180
|
+
whitespace = match.group(1)
|
|
181
|
+
dep_name = match.group(2)#pylint:disable=unused-variable
|
|
182
|
+
dep_operator = match.group(3) or None
|
|
183
|
+
dep_version = match.group(4) or None#pylint:disable=unused-variable
|
|
184
|
+
new_line=whitespace+name
|
|
185
|
+
if dep_operator is None:
|
|
186
|
+
dep_operator=">="
|
|
187
|
+
new_line=new_line+dep_operator+new_version
|
|
188
|
+
new_lines.append(new_line)
|
|
189
|
+
else:
|
|
190
|
+
new_lines.append(line)
|
|
191
|
+
GeneralUtilities.write_lines_to_file(setupcfg_file,new_lines)
|
|
192
|
+
|
|
193
|
+
def __set_dependency_version_in_requirementstxt(self,name:str,new_version:str)->None:
|
|
194
|
+
self.__set_dependency_version_in_requirements(name,new_version,os.path.join(self.get_codeunit_folder(),"requirements.txt"))
|
|
195
|
+
|
|
196
|
+
def __set_dependency_version_in_otherrequirementstxt(self,name:str,new_version:str)->None:
|
|
197
|
+
rfile=os.path.join(self.get_codeunit_folder(),"Other","requirements.txt")
|
|
198
|
+
if os.path.isfile(rfile):
|
|
199
|
+
self.__set_dependency_version_in_requirements(name,new_version,rfile)
|
|
200
|
+
|
|
201
|
+
def __set_dependency_version_in_requirements(self,name:str,new_version:str,requirementsfile:str)->None:
|
|
202
|
+
lines=GeneralUtilities.read_lines_from_file(requirementsfile)
|
|
203
|
+
new_lines:list[str]=[]
|
|
204
|
+
for line in lines:
|
|
205
|
+
match = re.match("^("+re.escape(name)+")\\s*([<>=!~]+)?\\s*(.*)?$", line)
|
|
206
|
+
if match:
|
|
207
|
+
dep_name = match.group(1)#pylint:disable=unused-variable
|
|
208
|
+
dep_operator = match.group(2) or None
|
|
209
|
+
dep_version = match.group(3) or None#pylint:disable=unused-variable
|
|
210
|
+
new_line=name
|
|
211
|
+
if dep_operator is None:
|
|
212
|
+
dep_operator=">="
|
|
213
|
+
new_line=new_line+dep_operator+new_version
|
|
214
|
+
new_lines.append(new_line)
|
|
215
|
+
else:
|
|
216
|
+
new_lines.append(line)
|
|
217
|
+
GeneralUtilities.write_lines_to_file(requirementsfile,new_lines)
|
|
218
|
+
|
|
219
|
+
class TFCPS_CodeUnitSpecific_Python_CLI:
|
|
220
|
+
|
|
221
|
+
@staticmethod
|
|
222
|
+
def parse(file:str)->TFCPS_CodeUnitSpecific_Python_Functions:
|
|
223
|
+
parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
|
|
224
|
+
#add custom parameter if desired
|
|
225
|
+
args=parser.parse_args()
|
|
226
|
+
result:TFCPS_CodeUnitSpecific_Python_Functions=TFCPS_CodeUnitSpecific_Python_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
|
|
227
|
+
return result
|
|
File without changes
|