scriptcollection 4.2.81__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.
Files changed (62) hide show
  1. ScriptCollection/AnionBuildPlatform.py +199 -0
  2. ScriptCollection/CertificateUpdater.py +149 -0
  3. ScriptCollection/Executables.py +921 -0
  4. ScriptCollection/GeneralUtilities.py +1589 -0
  5. ScriptCollection/HTTPMaintenanceOverheadHelper.py +36 -0
  6. ScriptCollection/OCIImages/AbstractImageHandler.py +38 -0
  7. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerDebian.py +20 -0
  8. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerDebianSlim.py +20 -0
  9. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGeneric.py +20 -0
  10. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGenericV.py +20 -0
  11. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGitlabCE.py +20 -0
  12. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGitlabEE.py +20 -0
  13. ScriptCollection/OCIImages/ConcreteImageHandlers/__init__.py +0 -0
  14. ScriptCollection/OCIImages/OCIImageManager.py +190 -0
  15. ScriptCollection/OCIImages/__init__.py +0 -0
  16. ScriptCollection/ProcessesRunner.py +43 -0
  17. ScriptCollection/ProgramRunnerBase.py +47 -0
  18. ScriptCollection/ProgramRunnerMock.py +2 -0
  19. ScriptCollection/ProgramRunnerPopen.py +57 -0
  20. ScriptCollection/ProgramRunnerSudo.py +108 -0
  21. ScriptCollection/Resources/CultureChooser/CultureChooser.js +29 -0
  22. ScriptCollection/Resources/CultureChooser/index.html +15 -0
  23. ScriptCollection/Resources/MaintenanceSite/MaintenanceSite.html +15 -0
  24. ScriptCollection/SCLog.py +115 -0
  25. ScriptCollection/ScriptCollectionCore.py +3485 -0
  26. ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py +192 -0
  27. ScriptCollection/TFCPS/Docker/__init__.py +0 -0
  28. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py +8 -0
  29. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py +6 -0
  30. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py +7 -0
  31. ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py +547 -0
  32. ScriptCollection/TFCPS/DotNet/__init__.py +0 -0
  33. ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py +137 -0
  34. ScriptCollection/TFCPS/Flutter/__init__.py +0 -0
  35. ScriptCollection/TFCPS/Go/TFCPS_CodeUnitSpecific_Go.py +72 -0
  36. ScriptCollection/TFCPS/Go/__init__.py +0 -0
  37. ScriptCollection/TFCPS/Maven/TFCPS_CodeUnitSpecific_Maven.py +42 -0
  38. ScriptCollection/TFCPS/Maven/__init__.py +0 -0
  39. ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py +232 -0
  40. ScriptCollection/TFCPS/NodeJS/__init__.py +0 -0
  41. ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py +239 -0
  42. ScriptCollection/TFCPS/Python/__init__.py +0 -0
  43. ScriptCollection/TFCPS/Rust/TFCPS_CodeUnitSpecific_Rust.py +42 -0
  44. ScriptCollection/TFCPS/Rust/__init__.py +0 -0
  45. ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py +433 -0
  46. ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py +135 -0
  47. ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py +301 -0
  48. ScriptCollection/TFCPS/TFCPS_CreateRelease.py +98 -0
  49. ScriptCollection/TFCPS/TFCPS_Generic.py +44 -0
  50. ScriptCollection/TFCPS/TFCPS_MergeToMain.py +128 -0
  51. ScriptCollection/TFCPS/TFCPS_MergeToStable.py +356 -0
  52. ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py +48 -0
  53. ScriptCollection/TFCPS/TFCPS_Tools_General.py +1565 -0
  54. ScriptCollection/TFCPS/__init__.py +0 -0
  55. ScriptCollection/__init__.py +0 -0
  56. ScriptCollection/__pycache__/GeneralUtilities.cpython-311.pyc +0 -0
  57. ScriptCollection/__pycache__/__init__.cpython-311.pyc +0 -0
  58. scriptcollection-4.2.81.dist-info/METADATA +169 -0
  59. scriptcollection-4.2.81.dist-info/RECORD +62 -0
  60. scriptcollection-4.2.81.dist-info/WHEEL +5 -0
  61. scriptcollection-4.2.81.dist-info/entry_points.txt +67 -0
  62. scriptcollection-4.2.81.dist-info/top_level.txt +1 -0
@@ -0,0 +1,137 @@
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
+ enabled=False
43
+ if enabled:#TODO move to external because this is not platform indepent
44
+ windows_release_folder = os.path.join(src_folder, "build/windows/x64/runner/Release")
45
+ windows_folder = os.path.join(artifacts_folder, "BuildResult_Windows")
46
+ GeneralUtilities.ensure_directory_does_not_exist(windows_folder)
47
+ GeneralUtilities.ensure_directory_exists(windows_folder)
48
+ GeneralUtilities.copy_content_of_folder(windows_release_folder, windows_folder)
49
+ elif target == "ios":
50
+ enabled=False
51
+ if enabled:#TODO move to external because this is not platform indepent
52
+ raise ValueError("building for ios is not implemented yet")
53
+ elif target == "appbundle":
54
+ enabled=False
55
+ if enabled:#TODO move to external because this is not platform indepent
56
+ aab_folder = os.path.join(artifacts_folder, "BuildResult_AAB")
57
+ GeneralUtilities.ensure_directory_does_not_exist(aab_folder)
58
+ GeneralUtilities.ensure_directory_exists(aab_folder)
59
+ aab_relase_folder = os.path.join(src_folder, "build/app/outputs/bundle/release")
60
+ aab_file_original = self._protected_sc.find_file_by_extension(aab_relase_folder, "aab")
61
+ aab_file = os.path.join(aab_folder, f"{codeunit_name}.aab")
62
+ shutil.copyfile(aab_file_original, aab_file)
63
+
64
+ bundletool = self.tfcps_Tools_General.ensure_androidappbundletool_is_available(None,self.use_cache())
65
+ apk_folder = os.path.join(artifacts_folder, "BuildResult_APK")
66
+ GeneralUtilities.ensure_directory_does_not_exist(apk_folder)
67
+ GeneralUtilities.ensure_directory_exists(apk_folder)
68
+ apks_file = f"{apk_folder}/{codeunit_name}.apks"
69
+ self._protected_sc.run_program("java", f"-jar {bundletool} build-apks --bundle={aab_file} --output={apks_file} --mode=universal", aab_relase_folder)
70
+ with zipfile.ZipFile(apks_file, "r") as zip_ref:
71
+ zip_ref.extract("universal.apk", apk_folder)
72
+ GeneralUtilities.ensure_file_does_not_exist(apks_file)
73
+ os.rename(f"{apk_folder}/universal.apk", f"{apk_folder}/{codeunit_name}.apk")
74
+ else:
75
+ raise ValueError(f"Not supported target: {target}")
76
+ self.copy_source_files_to_output_directory()
77
+
78
+ @GeneralUtilities.check_arguments
79
+ def linting(self) -> None:
80
+ pass#TODO
81
+
82
+ @GeneralUtilities.check_arguments
83
+ def do_common_tasks(self,current_codeunit_version:str )-> None:
84
+ self.do_common_tasks_base(current_codeunit_version)
85
+
86
+ @GeneralUtilities.check_arguments
87
+ def generate_reference(self) -> None:
88
+ self.generate_reference_using_docfx()
89
+
90
+
91
+ @GeneralUtilities.check_arguments
92
+ def run_testcases(self,package_name:str) -> None:
93
+ codeunit_folder = self.get_codeunit_folder()
94
+ repository_folder = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
95
+ codeunit_name = os.path.basename(codeunit_folder)
96
+ src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder)
97
+
98
+ self._protected_sc.run_with_epew("flutter", "test --coverage", src_folder)
99
+ test_coverage_folder_relative = "Other/Artifacts/TestCoverage"
100
+ test_coverage_folder = GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
101
+ GeneralUtilities.ensure_directory_exists(test_coverage_folder)
102
+ coverage_file_relative = f"{test_coverage_folder_relative}/TestCoverage.xml"
103
+ coverage_file = GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
104
+ self._protected_sc.run_with_epew("lcov_cobertura", f"coverage/lcov.info --base-dir . --excludes test --output ../{coverage_file_relative} --demangle", src_folder)
105
+
106
+ # format correctly
107
+ content = GeneralUtilities.read_text_from_file(coverage_file)
108
+ content = re.sub('<![^<]+>', '', content)
109
+ content = re.sub('\\\\', '/', content)
110
+ content = re.sub('\\ name=\\"lib\\"', '', content)
111
+ content = re.sub('\\ filename=\\"lib/', f' filename="{package_name}/lib/', content)
112
+ GeneralUtilities.write_text_to_file(coverage_file, content)
113
+ self.tfcps_Tools_General.merge_packages(coverage_file, self.get_codeunit_name())
114
+ self.tfcps_Tools_General.calculate_entire_line_rate(coverage_file)
115
+ self.run_testcases_common_post_task(repository_folder, codeunit_name, True, self.get_target_environment_type())
116
+
117
+
118
+ def get_dependencies(self)->dict[str,set[str]]:
119
+ return dict[str,set[str]]()#TODO
120
+
121
+ @GeneralUtilities.check_arguments
122
+ def get_available_versions(self,dependencyname:str)->list[str]:
123
+ return []#TODO
124
+
125
+ def set_dependency_version(self,name:str,new_version:str)->None:
126
+ raise ValueError(f"Operation is not implemented.")
127
+
128
+ class TFCPS_CodeUnitSpecific_Flutter_CLI:
129
+
130
+ @staticmethod
131
+ @GeneralUtilities.check_arguments
132
+ def parse(file:str)->TFCPS_CodeUnitSpecific_Flutter_Functions:
133
+ parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
134
+ #add custom parameter if desired
135
+ args=parser.parse_args()
136
+ result:TFCPS_CodeUnitSpecific_Flutter_Functions=TFCPS_CodeUnitSpecific_Flutter_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
137
+ return result
File without changes
@@ -0,0 +1,72 @@
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 dict[str,set[str]]()#TODO
54
+
55
+ @GeneralUtilities.check_arguments
56
+ def get_available_versions(self,dependencyname:str)->list[str]:
57
+ return []#TODO
58
+
59
+ @GeneralUtilities.check_arguments
60
+ def set_dependency_version(self,name:str,new_version:str)->None:
61
+ raise ValueError(f"Operation is not implemented.")
62
+
63
+ class TFCPS_CodeUnitSpecific_Go_CLI:
64
+
65
+ @staticmethod
66
+ @GeneralUtilities.check_arguments
67
+ def parse(file:str)->TFCPS_CodeUnitSpecific_Go_Functions:
68
+ parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
69
+ #add custom parameter if desired
70
+ args=parser.parse_args()
71
+ result:TFCPS_CodeUnitSpecific_Go_Functions=TFCPS_CodeUnitSpecific_Go_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
72
+ return result
File without changes
@@ -0,0 +1,42 @@
1
+ from ...GeneralUtilities import GeneralUtilities
2
+ from ...SCLog import LogLevel
3
+ from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base, TFCPS_CodeUnitSpecific_Base_CLI
4
+
5
+ class TFCPS_CodeUnitSpecific_Maven_Functions(TFCPS_CodeUnitSpecific_Base):
6
+
7
+ def __init__(self, current_file: str, verbosity: LogLevel, targetenvironmenttype: str, use_cache: bool, is_pre_merge: bool):
8
+ super().__init__(current_file, verbosity, targetenvironmenttype, use_cache, is_pre_merge)
9
+
10
+ @GeneralUtilities.check_arguments
11
+ def build(self) -> None:
12
+ pass#TODO
13
+
14
+ @GeneralUtilities.check_arguments
15
+ def linting(self) -> None:
16
+ pass#TODO
17
+
18
+ @GeneralUtilities.check_arguments
19
+ def run_testcases(self) -> None:
20
+ pass#TODO
21
+
22
+ def get_dependencies(self) -> dict[str, set[str]]:
23
+ return dict[str, set[str]]()#TODO
24
+
25
+ @GeneralUtilities.check_arguments
26
+ def get_available_versions(self, dependencyname: str) -> list[str]:
27
+ return []#TODO
28
+
29
+ @GeneralUtilities.check_arguments
30
+ def set_dependency_version(self, name: str, new_version: str) -> None:
31
+ raise ValueError("Operation is not implemented.")
32
+
33
+ class TFCPS_CodeUnitSpecific_Maven_CLI:
34
+
35
+ @staticmethod
36
+ @GeneralUtilities.check_arguments
37
+ def parse(file: str) -> TFCPS_CodeUnitSpecific_Maven_Functions:
38
+ parser = TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
39
+ #add custom parameter if desired
40
+ args = parser.parse_args()
41
+ result: TFCPS_CodeUnitSpecific_Maven_Functions = TFCPS_CodeUnitSpecific_Maven_Functions(file, LogLevel(int(args.verbosity)), args.targetenvironmenttype, not args.nocache, args.ispremerge)
42
+ return result
File without changes
@@ -0,0 +1,232 @@
1
+ import os
2
+ import re
3
+ import json
4
+ from pathlib import Path
5
+ import xml.etree.ElementTree as ET
6
+ from lxml import etree
7
+ from ...GeneralUtilities import GeneralUtilities
8
+ from ...SCLog import LogLevel
9
+ from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
10
+ from ...HTTPMaintenanceOverheadHelper import HTTPMaintenanceOverheadHelper
11
+
12
+ class TFCPS_CodeUnitSpecific_NodeJS_Functions(TFCPS_CodeUnitSpecific_Base):
13
+
14
+
15
+ def __init__(self,current_file:str,verbosity:LogLevel,targetenvironmenttype:str,use_cache:bool,is_pre_merge:bool):
16
+ super().__init__(current_file, verbosity,targetenvironmenttype,use_cache,is_pre_merge)
17
+
18
+
19
+ @GeneralUtilities.check_arguments
20
+ def build(self) -> None:
21
+ self._protected_sc.run_with_epew("npm", "run build", self.get_codeunit_folder(),print_live_output=self.get_verbosity()==LogLevel.Debug,encode_argument_in_base64=True)
22
+ self.standardized_tasks_build_bom_for_node_project()
23
+ self.copy_source_files_to_output_directory()
24
+
25
+ @GeneralUtilities.check_arguments
26
+ def linting(self) -> None:
27
+ src_folder = os.path.join(self.get_codeunit_folder(), "src")
28
+ for file in GeneralUtilities.get_all_files_of_folder(src_folder):
29
+ if file.endswith(".html"):
30
+ self._protected_sc.format_html_file(file, os.path.basename(file) == "index.html")
31
+ self._protected_sc.run_with_epew("npm", "run lint", self.get_codeunit_folder(),print_live_output=self.get_verbosity()==LogLevel.Debug,encode_argument_in_base64=True)
32
+
33
+ @GeneralUtilities.check_arguments
34
+ def do_common_tasks(self,current_codeunit_version:str)-> None:
35
+ codeunit_version = current_codeunit_version
36
+ codeunit_folder = self.get_codeunit_folder()
37
+ self.do_common_tasks_base(current_codeunit_version)
38
+ self.tfcps_Tools_General.replace_version_in_packagejson_file(GeneralUtilities.resolve_relative_path("./package.json", codeunit_folder), codeunit_version)
39
+ self.tfcps_Tools_General.do_npm_install(codeunit_folder, True,self.use_cache())
40
+ #if generateAPIClientBase.generate_api_client():
41
+ # generateAPIClientGenerate:GenerateAPIClientGenerate=generateAPIClientBase
42
+ # self.tfcps_Tools_General.generate_api_client_from_dependent_codeunit_in_angular(codeunit_folder, generateAPIClientGenerate.name_of_api_providing_codeunit,generateAPIClientGenerate.generate_api_client)
43
+
44
+ @GeneralUtilities.check_arguments
45
+ def generate_reference(self) -> None:
46
+ self.generate_reference_using_docfx()
47
+
48
+
49
+ @GeneralUtilities.check_arguments
50
+ def run_testcases(self) -> None:
51
+ # prepare
52
+ codeunit_name: str =self.get_codeunit_name()
53
+
54
+ codeunit_folder =self.get_codeunit_folder()
55
+ repository_folder = os.path.dirname(codeunit_folder)
56
+
57
+ # run testcases
58
+ self._protected_sc.run_with_epew("npm", f"run test-{self.get_target_environment_type()}", self.get_codeunit_folder(),print_live_output=self.get_verbosity()==LogLevel.Debug,encode_argument_in_base64=True)
59
+
60
+ # rename file
61
+ coverage_folder = os.path.join(codeunit_folder, "Other", "Artifacts", "TestCoverage")
62
+ target_file = os.path.join(coverage_folder, "TestCoverage.xml")
63
+ GeneralUtilities.ensure_file_does_not_exist(target_file)
64
+ os.rename(os.path.join(coverage_folder, "cobertura-coverage.xml"), target_file)
65
+ self.__rename_packagename_in_coverage_file(target_file, codeunit_name)
66
+
67
+ # adapt backslashs to slashs
68
+ content = GeneralUtilities.read_text_from_file(target_file)
69
+ content = re.sub('\\\\', '/', content)
70
+ GeneralUtilities.write_text_to_file(target_file, content)
71
+
72
+ # aggregate packages in testcoverage-file
73
+ roottree: etree._ElementTree = etree.parse(target_file)
74
+ existing_classes = list(roottree.xpath('//coverage/packages/package/classes/class'))
75
+
76
+ old_packages_list = roottree.xpath('//coverage/packages/package')
77
+ for package in old_packages_list:
78
+ package.getparent().remove(package)
79
+
80
+ root = roottree.getroot()
81
+ packages_element = root.find("packages")
82
+ package_element = etree.SubElement(packages_element, "package")
83
+ package_element.attrib['name'] = codeunit_name
84
+ package_element.attrib['lines-valid'] = root.attrib["lines-valid"]
85
+ package_element.attrib['lines-covered'] = root.attrib["lines-covered"]
86
+ package_element.attrib['line-rate'] = root.attrib["line-rate"]
87
+ package_element.attrib['branches-valid'] = root.attrib["branches-valid"]
88
+ package_element.attrib['branches-covered'] = root.attrib["branches-covered"]
89
+ package_element.attrib['branch-rate'] = root.attrib["branch-rate"]
90
+ package_element.attrib['timestamp'] = root.attrib["timestamp"]
91
+ package_element.attrib['complexity'] = root.attrib["complexity"]
92
+
93
+ classes_element = etree.SubElement(package_element, "classes")
94
+
95
+ for existing_class in existing_classes:
96
+ classes_element.append(existing_class)
97
+
98
+ result = etree.tostring(roottree, pretty_print=True).decode("utf-8")
99
+ GeneralUtilities.write_text_to_file(target_file, result)
100
+
101
+ # post tasks
102
+ self.run_testcases_common_post_task(repository_folder, codeunit_name, True, self.get_target_environment_type())
103
+
104
+ @GeneralUtilities.check_arguments
105
+ def __rename_packagename_in_coverage_file(self, file: str, codeunit_name: str) -> None:
106
+ root: etree._ElementTree = etree.parse(file)
107
+ packages = root.xpath('//coverage/packages/package')
108
+ for package in packages:
109
+ package.attrib['name'] = codeunit_name
110
+ result = etree.tostring(root).decode("utf-8")
111
+ GeneralUtilities.write_text_to_file(file, result)
112
+
113
+
114
+ @GeneralUtilities.check_arguments
115
+ def standardized_tasks_build_bom_for_node_project(self) -> None:
116
+ 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"
117
+ 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)
118
+ self._protected_sc.format_xml_file(self.get_codeunit_folder()+"/"+relative_path_to_bom_file)
119
+
120
+ def get_dependencies(self)->dict[str,set[str]]:
121
+ return dict[str,set[str]]()#TODO
122
+
123
+ @GeneralUtilities.check_arguments
124
+ def get_available_versions(self,dependencyname:str)->list[str]:
125
+ return []#TODO
126
+
127
+ @GeneralUtilities.check_arguments
128
+ def set_dependency_version(self,name:str,new_version:str)->None:
129
+ raise ValueError(f"Operation is not implemented.")
130
+
131
+ @GeneralUtilities.check_arguments
132
+ def add_culture_chooser(self,site_title:str,supported_cultures:list[str])->None:
133
+ output_folder=self.get_codeunit_folder()+"/Other/Artifacts/BuildResult_WebApplication/browser"
134
+ GeneralUtilities.assert_folder_exists(output_folder)
135
+ cc:HTTPMaintenanceOverheadHelper=HTTPMaintenanceOverheadHelper()
136
+
137
+ index_html_file=output_folder+"/index.html"
138
+ GeneralUtilities.ensure_file_exists(index_html_file)
139
+ index_html_content=cc.get_index_html(site_title)
140
+ GeneralUtilities.write_text_to_file(index_html_file, index_html_content)
141
+
142
+ cc_script_file=output_folder+"/CultureChooser.js"
143
+ GeneralUtilities.ensure_file_exists(cc_script_file)
144
+ cc_script_content=cc.get_culture_chooser_script(supported_cultures)
145
+ GeneralUtilities.write_text_to_file(cc_script_file, cc_script_content)
146
+
147
+ @GeneralUtilities.check_arguments
148
+ def add_maintenance_site(self,site_title:str)->None:
149
+ output_folder_base=self.get_codeunit_folder()+"/Other/Artifacts/BuildResult_WebApplication"
150
+ GeneralUtilities.assert_folder_exists(output_folder_base)
151
+ output_folder=os.path.join(output_folder_base,"maintenance")
152
+ GeneralUtilities.ensure_directory_exists(output_folder)
153
+ cc:HTTPMaintenanceOverheadHelper=HTTPMaintenanceOverheadHelper()
154
+
155
+ maintenance_file=output_folder+"/MaintenanceSite.html"
156
+ GeneralUtilities.ensure_file_exists(maintenance_file)
157
+ maintenance_content=cc.get_maintenance_file(site_title)
158
+ GeneralUtilities.write_text_to_file(maintenance_file, maintenance_content)
159
+
160
+
161
+ @GeneralUtilities.check_arguments
162
+ def get_available_cultures_for_angular_app(self)->None:
163
+ return self._protected_sc.get_available_cultures_for_angular_app(self.get_codeunit_folder()+"/angular.json")
164
+
165
+ @GeneralUtilities.check_arguments
166
+ def __ensure_translations_exist(self,languages:list[str])->None:
167
+ base_file=os.path.join(self.get_codeunit_folder(),"Other","Resources","Translations",f"messages.xlf")
168
+ for language in languages:
169
+ target_file=os.path.join(self.get_codeunit_folder(),"Other","Resources","Translations",f"messages.{language}.xlf")
170
+ if not os.path.isfile(target_file):
171
+ GeneralUtilities.ensure_file_exists(target_file)
172
+ GeneralUtilities.write_text_to_file(target_file, GeneralUtilities.read_text_from_file(base_file))
173
+ #set new attribute
174
+ tree = ET.parse(target_file)
175
+ root = tree.getroot()
176
+ ns_prefix = "{urn:oasis:names:tc:xliff:document:2.0}"
177
+ for unit in root.findall(f".//{ns_prefix}unit"):
178
+ for segment in unit.findall(f"{ns_prefix}segment"):
179
+ segment.set("state", "initial")
180
+ tree.write(target_file, encoding="utf-8", xml_declaration=True)
181
+
182
+ angular_json_file=self.get_codeunit_folder()+"/angular.json"
183
+ if os.path.isfile(angular_json_file):
184
+ angular_json_path = Path(angular_json_file)
185
+ with angular_json_path.open(encoding="utf-8") as f:
186
+ angular_config = json.load(f)
187
+ i18n_config = angular_config["projects"][self.get_codeunit_name()]["i18n"]
188
+ new_locales = {
189
+ lang: f"Other/Resources/Translations/messages.{lang}.xlf"
190
+ for lang in languages
191
+ }
192
+ i18n_config.setdefault("locales", {}).update(new_locales)
193
+ with angular_json_path.open("w", encoding="utf-8") as f:
194
+ json.dump(angular_config, f, ensure_ascii=False, indent=2)
195
+
196
+ @GeneralUtilities.check_arguments
197
+ def organize_translations(self,languages:list[str])->None:
198
+ self._protected_sc.run_with_epew("npm","run extract-translations",self.get_codeunit_folder())
199
+ self.__ensure_translations_exist(languages)
200
+ self._protected_sc.sync_xlf2_files("messages",languages,os.path.join(self.get_codeunit_folder(),"Other","Resources","Translations"))
201
+
202
+ @GeneralUtilities.check_arguments
203
+ def translate_safe(self,base_language:str="en", throw_if_no_credentials:bool=False)->None:
204
+ """Translates XLF files if a translation service is configured. The translation service can be configured by creating a file at ~/.ScriptCollection/TranslationServiceProperties.txt with the content 'LibreTranslateAPI=your_api_server_url'."""
205
+ translationservice_file:str=self._protected_sc.get_global_cache_folder()+"/TranslationServiceProperties.txt"
206
+ api_server:str=None
207
+ if os.path.isfile(translationservice_file):
208
+ lines=GeneralUtilities.read_nonempty_lines_from_file(translationservice_file)
209
+ for line in lines:
210
+ if line.startswith("LibreTranslateAPI="):
211
+ api_server=line.replace("LibreTranslateAPI=","").strip()
212
+ if api_server is None:
213
+ if throw_if_no_credentials:
214
+ raise ValueError("No translation service configured. Please create a file at ~/.ScriptCollection/TranslationServiceProperties.txt with the content 'LibreTranslateAPI=your_api_server_url' to enable automatic translation of XLF files.")
215
+ else:
216
+ self.translate(api_server,base_language)
217
+
218
+ @GeneralUtilities.check_arguments
219
+ def translate(self,api_server:str,base_language:str="en")->None:
220
+ folder:str=os.path.join(self.get_codeunit_folder(),"Other","Resources","Translations")
221
+ self._protected_sc.translate_xlf_files_in_folder(folder, base_language, api_server)
222
+
223
+ class TFCPS_CodeUnitSpecific_NodeJS_CLI:
224
+
225
+ @staticmethod
226
+ @GeneralUtilities.check_arguments
227
+ def parse(file:str)->TFCPS_CodeUnitSpecific_NodeJS_Functions:
228
+ parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
229
+ #add custom parameter if desired
230
+ args=parser.parse_args()
231
+ result:TFCPS_CodeUnitSpecific_NodeJS_Functions=TFCPS_CodeUnitSpecific_NodeJS_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
232
+ return result
File without changes