ScriptCollection 4.2.69__py3-none-any.whl → 4.2.70__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.
@@ -1454,6 +1454,18 @@ class GeneralUtilities:
1454
1454
  else:
1455
1455
  raise ValueError(f"Unsupported platform: {system}/{machine}")
1456
1456
 
1457
+ @staticmethod
1458
+ @check_arguments
1459
+ def current_system_is_x64():
1460
+ arch = platform.machine().lower()
1461
+ return arch in ("x86_64", "amd64")
1462
+
1463
+ @staticmethod
1464
+ @check_arguments
1465
+ def current_system_is_arm64():
1466
+ arch = platform.machine().lower()
1467
+ return arch in ("arm", "aarch64")
1468
+
1457
1469
  @staticmethod
1458
1470
  @check_arguments
1459
1471
  def platform_to_short_str(platform_value: Platform) -> str:
@@ -1523,6 +1535,14 @@ class GeneralUtilities:
1523
1535
  Platform.MacOS_ARM64: "osx-arm64",
1524
1536
  }
1525
1537
  return mapping[platform_value]
1538
+ @staticmethod
1539
+ @check_arguments
1540
+ def platform_to_go_runtime_identifier(platform_value: Platform) -> str:
1541
+ mapping = {
1542
+ Platform.Linux_AMD64: "amd64",
1543
+ Platform.Linux_ARM64: "arm64",
1544
+ }
1545
+ return mapping[platform_value]
1526
1546
 
1527
1547
  @staticmethod
1528
1548
  @check_arguments
@@ -37,7 +37,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
37
37
  from .ProgramRunnerPopen import ProgramRunnerPopen
38
38
  from .SCLog import SCLog, LogLevel
39
39
 
40
- version = "4.2.69"
40
+ version = "4.2.70"
41
41
  __version__ = version
42
42
 
43
43
  class VSCodeWorkspaceShellTask:
@@ -214,6 +214,19 @@ class ScriptCollectionCore:
214
214
  GeneralUtilities.assert_not_null(registry_username)
215
215
  return (registry_username,registry_password)
216
216
 
217
+ def __get_docker_registry_credentials(self)->list[tuple[str,str,str]]:
218
+ result=[]
219
+ credential_file=self.__get_docker_registry_credentials_file()
220
+ if os.path.isfile(credential_file):
221
+ lines=GeneralUtilities.read_nonempty_lines_from_file(credential_file)[1:]
222
+ for line in lines:
223
+ splitted=line.split(";")
224
+ registry=splitted[0]
225
+ username=splitted[1]
226
+ password=splitted[2]
227
+ result.append((registry,username,password))
228
+ return result
229
+
217
230
  def registry_contains_image(self,registry_url:str,image:str,registry_username:str,registry_password:str)->bool:
218
231
  """This function assumes that the registry is a custom deployed docker-registry (see https://hub.docker.com/_/registry )"""
219
232
  try:
@@ -287,6 +300,16 @@ class ScriptCollectionCore:
287
300
  else:
288
301
  result = tag in tags
289
302
  return result
303
+
304
+ def login_to_defined_docker_registries(self)->None:
305
+ registries=self.__get_docker_registry_credentials()
306
+ if len(registries)==0:
307
+ self.log.log("No docker registry credentials defined. Skipping docker login.",LogLevel.Debug)
308
+ else:
309
+ for registry,username,password in registries:
310
+ arg=f"login {registry} -u {username} -p {password}"
311
+ arg_for_log=f"login {registry} -u {username} -p ***"
312
+ self.run_program("docker",arg,arguments_for_log=arg_for_log,print_live_output=self.log.loglevel==LogLevel.Debug)
290
313
 
291
314
  @GeneralUtilities.check_arguments
292
315
  def python_file_has_errors(self, file: str, working_directory: str, treat_warnings_as_errors: bool = True) -> tuple[bool, list[str]]:
@@ -712,6 +735,7 @@ class ScriptCollectionCore:
712
735
  self.git_merge(repository_folder, f"{remote}/{branch}", branch)
713
736
  self.git_push_with_retry(repository_folder, remote, branch, branch)
714
737
  self.git_checkout(repository_folder, branch)
738
+ #TODO opeional: checkfor merge conflicts and if there is one merge conflict print a warning
715
739
 
716
740
  @GeneralUtilities.check_arguments
717
741
  def git_merge_abort(self, directory: str) -> None:
@@ -2618,11 +2642,36 @@ TXDX
2618
2642
  encoding
2619
2643
  )
2620
2644
 
2645
+ @GeneralUtilities.check_arguments
2646
+ def get_pip_index_url_arguments_from_local_cache(self)->list[str]:
2647
+ arguments=[]
2648
+ pip_folder=GeneralUtilities.normalize_path(self.get_global_cache_folder()+"/Pip")
2649
+ if os.path.isdir(pip_folder):
2650
+ main_index_file=GeneralUtilities.normalize_path(os.path.join(pip_folder, "MainIndex.txt"))
2651
+ if os.path.isfile(main_index_file):
2652
+ lines=GeneralUtilities.read_nonempty_lines_from_file(main_index_file)
2653
+ url=[line for line in lines if line.startswith("IndexURL: ")][0].split(":")[1].strip()
2654
+ arguments.append("--index-url")
2655
+ arguments.append(url)
2656
+ extra_index_folder=GeneralUtilities.normalize_path(os.path.join(pip_folder, "ExtraIndexURLs"))
2657
+ if os.path.isdir(extra_index_folder):
2658
+ index_files=GeneralUtilities.get_direct_files_of_folder(extra_index_folder)
2659
+ if len(index_files) > 0:
2660
+ for indexurl_file in index_files:
2661
+ lines=GeneralUtilities.read_nonempty_lines_from_file(indexurl_file)
2662
+ url=[line for line in lines if line.startswith("IndexURL: ")][0].split(":")[1].strip()
2663
+ arguments.append("--extra-index-url")
2664
+ arguments.append(url)
2665
+ return arguments
2666
+
2621
2667
  @GeneralUtilities.check_arguments
2622
2668
  def install_requirementstxt_file(self, requirements_txt_file: str):
2623
2669
  folder: str = os.path.dirname(requirements_txt_file)
2624
2670
  filename: str = os.path.basename(requirements_txt_file)
2625
- self.run_program_argsasarray("pip", ["install", "-r", filename], folder)
2671
+ arguments= ["install", "-r", filename]
2672
+ for argument in self.get_pip_index_url_arguments_from_local_cache():
2673
+ arguments.append(argument)
2674
+ self.run_program_argsasarray("pip", arguments, folder,print_live_output=self.log.loglevel==LogLevel.Debug)
2626
2675
 
2627
2676
  @GeneralUtilities.check_arguments
2628
2677
  def ocr_analysis_of_folder(self, folder: str, serviceaddress: str, extensions: list[str], languages: list[str], datafolder: str,base_folder_for_entry: str,ignore_pattern:list[str] ) -> list[str]: # Returns a list of changed files due to ocr-analysis.
@@ -3272,3 +3321,8 @@ OCR-content:
3272
3321
  commits=self.get_all_commits_in_git_repository(repository_folder, include_all_heads)
3273
3322
  GeneralUtilities.ensure_file_exists(target_file)
3274
3323
  GeneralUtilities.write_lines_to_file(target_file, commits)
3324
+
3325
+
3326
+ @GeneralUtilities.check_arguments
3327
+ def is_runnning_in_container(self) ->bool:
3328
+ return os.environ.get("ISRUNNINGINCONTAINER") == "true"
@@ -28,10 +28,14 @@ class TFCPS_CodeUnitSpecific_Docker_Functions(TFCPS_CodeUnitSpecific_Base):
28
28
  GeneralUtilities.ensure_folder_exists_and_is_empty(app_artifacts_folder)
29
29
  for platform in platforms:
30
30
  #builder must be created once before with "docker buildx create --use"
31
- args = ["buildx","build", "--platform",GeneralUtilities.platform_to_docker_platform_str(platform), "--pull", "--force-rm", "--progress=plain", "--build-arg", f"TargetEnvironmentType={self.get_target_environment_type()}", "--build-arg", f"CodeUnitName={codeunitname}", "--build-arg", f"CodeUnitVersion={codeunitversion}", "--build-arg", f"CodeUnitOwnerName={self.tfcps_Tools_General.get_codeunit_owner_name(self.get_codeunit_file())}", "--build-arg", f"CodeUnitOwnerEMailAddress={self.tfcps_Tools_General.get_codeunit_owner_emailaddress(self.get_codeunit_file())}", "--build-arg", f"Platform={GeneralUtilities.platform_to_dash_str(platform)}", "--build-arg", f"DotNetRuntime={GeneralUtilities.platform_to_dotnet_runtime_identifier(platform)}"]
31
+ args = ["buildx","build", "--platform",GeneralUtilities.platform_to_docker_platform_str(platform), "--pull", "--force-rm", "--progress=plain", "--build-arg", f"TargetEnvironmentType={self.get_target_environment_type()}", "--build-arg", f"CodeUnitName={codeunitname}", "--build-arg", f"CodeUnitVersion={codeunitversion}", "--build-arg", f"CodeUnitOwnerName={self.tfcps_Tools_General.get_codeunit_owner_name(self.get_codeunit_file())}", "--build-arg", f"CodeUnitOwnerEMailAddress={self.tfcps_Tools_General.get_codeunit_owner_emailaddress(self.get_codeunit_file())}", "--build-arg", f"Platform={GeneralUtilities.platform_to_dash_str(platform)}", "--build-arg", f"DotNetRuntime={GeneralUtilities.platform_to_dotnet_runtime_identifier(platform)}", "--build-arg", f"PlatformForGoVersion={GeneralUtilities.platform_to_go_runtime_identifier(platform)}"]
32
32
  for custom_argument_key, custom_argument_value in custom_arguments.items():
33
33
  args.append("--build-arg")
34
34
  args.append(f"{custom_argument_key}={custom_argument_value}")
35
+ pip_args=self._protected_sc.get_pip_index_url_arguments_from_local_cache()
36
+ if len(pip_args)>0:
37
+ args.append("--build-arg")
38
+ args.append(f"PipIndexUrlArguments=\"{pip_args}\"")
35
39
  args = args+["--tag", f"{codeunitname_lower}:latest", "--tag", f"{codeunitname_lower}:{codeunitversion}", "--file", f"{codeunitname}/Dockerfile"]
36
40
  if not self.use_cache():
37
41
  args.append("--no-cache")
@@ -40,13 +44,14 @@ class TFCPS_CodeUnitSpecific_Docker_Functions(TFCPS_CodeUnitSpecific_Base):
40
44
  args.append(f"type=docker,dest={target_file}")
41
45
  args.append(".")
42
46
  self._protected_sc.run_program_argsasarray("docker", args, codeunit_folder, print_errors_as_information=True,print_live_output=self.get_verbosity()==LogLevel.Debug)
47
+ self._protected_sc.run_program_argsasarray("docker", ["load", "-i", target_file], codeunit_folder, print_errors_as_information=True,print_live_output=self.get_verbosity()==LogLevel.Debug)
48
+
43
49
  self.__generate_sbom_for_docker_image()
44
50
  self.copy_source_files_to_output_directory()
45
51
 
46
52
 
47
53
  @GeneralUtilities.check_arguments
48
54
  def __generate_sbom_for_docker_image(self) -> None:
49
- return #FIXME due to the change of building docker images now using "docker builx build ..." the image is not available locally anymore. for this reason syft can not access the "product:tag"-image anymore to generate a sbom-file. solution: the tar-file must be loaded and tagged.
50
55
  codeunitname=self.get_codeunit_name()
51
56
  codeunit_folder =self.get_codeunit_folder()
52
57
  artifacts_folder = GeneralUtilities.resolve_relative_path("Other/Artifacts", codeunit_folder)
@@ -1,131 +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
- 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 dict[str,set[str]]()#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
- @GeneralUtilities.check_arguments
126
- def parse(file:str)->TFCPS_CodeUnitSpecific_Flutter_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_Flutter_Functions=TFCPS_CodeUnitSpecific_Flutter_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
131
- return result
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
@@ -196,7 +196,7 @@ class TFCPS_CodeUnitSpecific_NodeJS_Functions(TFCPS_CodeUnitSpecific_Base):
196
196
  self._protected_sc.sync_xlf2_files("messages",languages,os.path.join(self.get_codeunit_folder(),"Other","Resources","Translations"))
197
197
 
198
198
  @GeneralUtilities.check_arguments
199
- def translate_safe(self,base_language:str="en")->None:
199
+ def translate_safe(self,base_language:str="en", throw_if_no_credentials:bool=False)->None:
200
200
  """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'."""
201
201
  translationservice_file:str=self._protected_sc.get_global_cache_folder()+"/TranslationServiceProperties.txt"
202
202
  api_server:str=None
@@ -205,8 +205,11 @@ class TFCPS_CodeUnitSpecific_NodeJS_Functions(TFCPS_CodeUnitSpecific_Base):
205
205
  for line in lines:
206
206
  if line.startswith("LibreTranslateAPI="):
207
207
  api_server=line.replace("LibreTranslateAPI=","").strip()
208
- GeneralUtilities.assert_not_null(api_server,"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.")
209
- self.translate(api_server,base_language)
208
+ if api_server is None:
209
+ if throw_if_no_credentials:
210
+ 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.")
211
+ else:
212
+ self.translate(api_server,base_language)
210
213
 
211
214
  @GeneralUtilities.check_arguments
212
215
  def translate(self,api_server:str,base_language:str="en")->None:
@@ -37,12 +37,14 @@ class TFCPS_CodeUnitSpecific_Python_Functions(TFCPS_CodeUnitSpecific_Base):
37
37
  bom_file_json = os.path.join(codeunit_folder, bom_file_relative_json)
38
38
  bom_file_xml = os.path.join(codeunit_folder, bom_file_relative_xml)
39
39
 
40
- GeneralUtilities.ensure_file_exists(bom_file_json)
41
- GeneralUtilities.write_text_to_file(bom_file_json, result[1])
42
- cyclonedx_exe=self.tfcps_Tools_General.ensure_cyclonedxcli_is_available(not self.use_cache())
43
- 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)
44
- self._protected_sc.format_xml_file(bom_file_xml)
45
- GeneralUtilities.ensure_file_does_not_exist(bom_file_json)
40
+ enabled:bool=False
41
+ if enabled:#TODO cyclonedx must be available for all platforms in the global sc-cache-folder
42
+ GeneralUtilities.ensure_file_exists(bom_file_json)
43
+ GeneralUtilities.write_text_to_file(bom_file_json, result[1])
44
+ cyclonedx_exe=self.tfcps_Tools_General.ensure_cyclonedxcli_is_available(not self.use_cache())
45
+ 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)
46
+ self._protected_sc.format_xml_file(bom_file_xml)
47
+ GeneralUtilities.ensure_file_does_not_exist(bom_file_json)
46
48
 
47
49
  @GeneralUtilities.check_arguments
48
50
  def linting(self) -> None:
@@ -167,7 +167,7 @@ class TFCPS_CodeUnitSpecific_Base(ABC):
167
167
  if not os.path.isfile(combined_file):
168
168
  raise ValueError(f'The mandatory file "{file}" does not exist in the codeunit-folder.')
169
169
 
170
- if os.path.isfile(os.path.join(codeunit_folder, "Other", "requirements.txt")):
170
+ if os.path.isfile(os.path.join(codeunit_folder, "requirements.txt")):
171
171
  self.install_requirementstxt_for_codeunit()
172
172
 
173
173
  # check developer
@@ -416,7 +416,7 @@ class TFCPS_CodeUnitSpecific_Base(ABC):
416
416
 
417
417
  @GeneralUtilities.check_arguments
418
418
  def install_requirementstxt_for_codeunit(self):
419
- self._protected_sc.install_requirementstxt_file(self.get_codeunit_folder()+"/Other/requirements.txt")
419
+ self._protected_sc.install_requirementstxt_file(self.get_codeunit_folder()+"/requirements.txt")
420
420
 
421
421
  class TFCPS_CodeUnitSpecific_Base_CLI():
422
422
 
@@ -79,7 +79,9 @@ class TFCPS_CodeUnit_BuildCodeUnits:
79
79
  pre_script_file:str=os.path.join( self.sc.get_scriptcollection_configuration_folder(),"TFCPS","CustomPreCodeUnitBuildScript.py")
80
80
  if os.path.isfile( pre_script_file):
81
81
  self.sc.log.log("Run custom pre-codeunitbuild script...")
82
- argument= f"CustomPreCodeUnitBuildScript.py --repository \"{self.repository}\" --targetenvironmenttype {self.target_environment_type} --additionalargumentsfile \"{self.additionalargumentsfile}\" --verbosity {int(self.sc.log.loglevel)}"
82
+ argument= f"CustomPreCodeUnitBuildScript.py --repository {self.repository} --targetenvironmenttype {self.target_environment_type} --verbosity {int(self.sc.log.loglevel)}"
83
+ if GeneralUtilities.string_has_content(self.additionalargumentsfile):
84
+ argument=f"{argument} --additionalargumentsfile {self.additionalargumentsfile}"
83
85
  if not self.__use_cache:
84
86
  argument=f"{argument} --nocache"
85
87
  self.sc.run_program("python",argument, os.path.join( self.sc.get_scriptcollection_configuration_folder(),"TFCPS"),print_live_output=True)
@@ -39,15 +39,33 @@ class TFCPS_Tools_General:
39
39
 
40
40
  @GeneralUtilities.check_arguments
41
41
  def ensure_cyclonedxcli_is_available(self,enforce_update:bool) -> str:
42
- local_filename = "cyclonedx-cli"
43
- filename_on_github: str
42
+ local_resource_name="CycloneDXCLI"
43
+ self.ensure_file_from_github_assets_is_available_with_retry("CycloneDX", "cyclonedx-cli", local_resource_name,"cyclonedx-linux-arm64",lambda latest_version: "cyclonedx-linux-arm64",enforce_update=enforce_update)
44
+ self.ensure_file_from_github_assets_is_available_with_retry("CycloneDX", "cyclonedx-cli", local_resource_name,"cyclonedx-linux-x64",lambda latest_version: "cyclonedx-linux-x64",enforce_update=enforce_update)
45
+ self.ensure_file_from_github_assets_is_available_with_retry("CycloneDX", "cyclonedx-cli", local_resource_name,"cyclonedx-win-arm64.exe",lambda latest_version: "cyclonedx-win-arm64.exe",enforce_update=enforce_update)
46
+ self.ensure_file_from_github_assets_is_available_with_retry("CycloneDX", "cyclonedx-cli", local_resource_name, "cyclonedx-win-x64.exe",lambda latest_version: "cyclonedx-win-x64.exe",enforce_update=enforce_update)
47
+
48
+ resource_folder =os.path.join( self.__sc.get_global_cache_folder(),"Tools",local_resource_name)
49
+
50
+ is_x64:bool=GeneralUtilities.current_system_is_x64()
51
+ is_arm:bool=GeneralUtilities.current_system_is_arm64()
44
52
  if GeneralUtilities.current_system_is_windows():
45
- filename_on_github = "cyclonedx-win-x64.exe"
46
- local_filename = local_filename+".exe"
53
+ if is_x64:
54
+ return os.path.join(resource_folder, "cyclonedx-win-x64.exe")
55
+ elif is_arm:
56
+ return os.path.join(resource_folder, "cyclonedx-win-arm64.exe")
57
+ else:
58
+ raise ValueError("Unsupported architecture for cyclonedx-cli on windows.")
59
+ elif GeneralUtilities.current_system_is_linux():
60
+ if is_x64:
61
+ return os.path.join(resource_folder, "cyclonedx-linux-x64")
62
+ elif is_arm:
63
+ return os.path.join(resource_folder, "cyclonedx-linux-arm64")
64
+ else:
65
+ raise ValueError("Unsupported architecture for cyclonedx-cli on linux.")
47
66
  else:
48
- filename_on_github = "cyclonedx-linux-x64"
49
- return self.ensure_file_from_github_assets_is_available_with_retry("CycloneDX", "cyclonedx-cli", "CycloneDXCLI",local_filename,lambda latest_version: filename_on_github,enforce_update=enforce_update)
50
-
67
+ raise ValueError("Unsupported operating system for cyclonedx-cli.")
68
+
51
69
  @GeneralUtilities.check_arguments
52
70
  def ensure_file_from_github_assets_is_available_with_retry(self, githubuser: str, githubprojectname: str, local_resource_name: str, local_filename: str, get_filename_on_github, amount_of_attempts: int = 5,enforce_update:bool=False) -> str:
53
71
  return GeneralUtilities.retry_action(lambda: self.ensure_file_from_github_assets_is_available(githubuser, githubprojectname, local_resource_name, local_filename, get_filename_on_github,enforce_update), amount_of_attempts)
@@ -384,6 +402,7 @@ class TFCPS_Tools_General:
384
402
 
385
403
  @GeneralUtilities.check_arguments
386
404
  def generate_diff_report(self, repository_folder: str, codeunit_name: str, current_version: str) -> None:
405
+ #TODO refactor this. if new changes (committed or uncommitted) since last git-tag: diff-report from last tag to "now". if no new changes (curren-commit==commit on a vx.y-tag): take diff from last tag to this tag
387
406
  self.__sc.assert_is_git_repository(repository_folder)
388
407
  codeunit_folder = os.path.join(repository_folder, codeunit_name)
389
408
  target_folder = GeneralUtilities.resolve_relative_path("Other/Artifacts/DiffReport", codeunit_folder)
@@ -1182,21 +1201,21 @@ class TFCPS_Tools_General:
1182
1201
  tar_files_with_platforms: list[tuple[str, str, str]] = []
1183
1202
  for tar_file in tar_files:
1184
1203
  filename=os.path.basename(tar_file)#filename looks like "{codeunitname}_v{codeunitversion}_{GeneralUtilities.platform_to_dash_str(platform)}.tar"
1185
- platform:Platform=self.platform_from_filename(filename)#GeneralUtilities.platform_from_dash_str( filename.split("_")[-1].split(".")[0])
1204
+ platform_of_file:Platform=self.platform_from_filename(filename)#GeneralUtilities.platform_from_dash_str( filename.split("_")[-1].split(".")[0])
1186
1205
  platform_os_in_docker_format :str = None
1187
1206
  platform_arch_in_docker_format :str = None
1188
- if platform==Platform.Windows_AMD64:
1207
+ if platform_of_file==Platform.Windows_AMD64:
1189
1208
  raise NotImplementedError("Building docker images for Windows is not implemented yet.")
1190
- elif platform==Platform.Linux_AMD64:
1209
+ elif platform_of_file==Platform.Linux_AMD64:
1191
1210
  platform_os_in_docker_format = "linux"
1192
1211
  platform_arch_in_docker_format = "amd64"
1193
- elif platform==Platform.Linux_ARM64:
1212
+ elif platform_of_file==Platform.Linux_ARM64:
1194
1213
  platform_os_in_docker_format = "linux"
1195
1214
  platform_arch_in_docker_format = "arm64"
1196
- elif platform==Platform.MacOS_ARM64:
1215
+ elif platform_of_file==Platform.MacOS_ARM64:
1197
1216
  raise NotImplementedError("Building docker images for MacOS is not implemented yet.")
1198
1217
  else:
1199
- raise ValueError(f"Unsupported platform {platform} extracted from filename {filename}.")
1218
+ raise ValueError(f"Unsupported platform {platform_of_file} extracted from filename {filename}.")
1200
1219
  tar_files_with_platforms.append((tar_file, platform_os_in_docker_format, platform_arch_in_docker_format))
1201
1220
  self.push_docker_build_artifact_as_multi_arch_artifact(tar_files_with_platforms,target_image_address, "v"+codeunit_version)
1202
1221
  self.push_docker_build_artifact_as_multi_arch_artifact(tar_files_with_platforms,target_image_address, "latest")
@@ -1272,14 +1291,14 @@ class TFCPS_Tools_General:
1272
1291
  self.__sc.run_program("docker", f"container rm -f {container_name}", throw_exception_if_exitcode_is_not_zero=False)
1273
1292
 
1274
1293
  @GeneralUtilities.check_arguments
1275
- def load_docker_image(self, oci_image_artifacts_folder:str,platform:Platform) -> None:
1276
- for file in GeneralUtilities.get_direct_files_of_folder(oci_image_artifacts_folder):
1277
- if file.endswith(f"_{GeneralUtilities.platform_to_dash_str(platform)}.tar"):
1294
+ def load_docker_image(self, oci_image_artifacts_folder:str,platform_for_image:Platform) -> None:
1295
+ for file in GeneralUtilities.get_direct_files_of_folder(oci_image_artifacts_folder):
1296
+ if file.endswith(f"_{GeneralUtilities.platform_to_dash_str(platform_for_image)}.tar"):
1278
1297
  image_filename = file
1279
- self.__sc.log.log("Load docker-image...")
1298
+ self.__sc.log.log(f"Load docker-image {image_filename}...")
1280
1299
  self.__sc.run_program("docker", f"load -i {image_filename}", oci_image_artifacts_folder)
1281
1300
  return
1282
- raise ValueError(f"No docker-image found for platform {GeneralUtilities.platform_to_dash_str(platform)} in folder {oci_image_artifacts_folder}.")
1301
+ raise ValueError(f"No docker-image found for platform {GeneralUtilities.platform_to_dash_str(platform_for_image)} in folder {oci_image_artifacts_folder}.")
1283
1302
 
1284
1303
  @GeneralUtilities.check_arguments
1285
1304
  def start_dockerfile_example(self, current_file: str,remove_old_container: bool, remove_volumes_folder: bool, env_file: str) -> None:
@@ -1294,7 +1313,14 @@ class TFCPS_Tools_General:
1294
1313
  self.__sc.log.log(f"Ensure container of {docker_compose_file} do not exist...")
1295
1314
  oci_image_artifacts_folder = GeneralUtilities.resolve_relative_path("../../../../Artifacts/BuildResult_OCIImage", folder_of_current_file)
1296
1315
  self.ensure_containers_are_not_running(container_names_to_remove)
1297
- self.load_docker_image(oci_image_artifacts_folder,GeneralUtilities.get_current_platform())
1316
+ platform_for_image :Platform=None
1317
+ if GeneralUtilities.current_system_is_x64():
1318
+ platform_for_image=Platform.Linux_AMD64
1319
+ elif GeneralUtilities.current_system_is_arm64():
1320
+ platform_for_image=Platform.Linux_ARM64
1321
+ else:
1322
+ raise ValueError("Unsupported platform for docker-image. Only AMD64 and ARM64 are supported.")
1323
+ self.load_docker_image(oci_image_artifacts_folder,platform_for_image)
1298
1324
  example_name = os.path.basename(folder_of_current_file)
1299
1325
  codeunit_name = os.path.basename(GeneralUtilities.resolve_relative_path("../../../../..", folder_of_current_file))
1300
1326
  if remove_volumes_folder:
@@ -1428,8 +1454,10 @@ class TFCPS_Tools_General:
1428
1454
  for image in self.oci_image_manager.get_used_images_in_repository(repository_folder):
1429
1455
  env_variables[f"image_{image.lower()}"]=self.oci_image_manager.get_registry_address_for_image(repository_folder,image)+":"+self.oci_image_manager.get_tag_for_image(repository_folder,image, True)
1430
1456
  test_services=GeneralUtilities.get_direct_folders_of_folder(os.path.join(repository_folder,"Other","Resources","LocalTestServices"))
1431
- if 0<len(test_services):
1432
- self.__sc.log.log("Pull images for local test-services...")
1457
+ if len(test_services)==0:
1458
+ return
1459
+ self.__sc.log.log("Pull images for local test-services...")
1460
+ self.__sc.login_to_defined_docker_registries()
1433
1461
  for test_service_folder in test_services:
1434
1462
  test_service_name=os.path.basename(test_service_folder)
1435
1463
  self.__sc.log.log(f"Pull images for test-service {test_service_name}...")
@@ -1441,7 +1469,8 @@ class TFCPS_Tools_General:
1441
1469
  lines=lines+[f"{k}={v}"]
1442
1470
  GeneralUtilities.write_lines_to_file(env_variables_file,lines)
1443
1471
  arguments=arguments + " --env-file Parameters.env pull --quiet"
1444
- self.__sc.run_program_with_retry("docker",arguments,test_service_folder,print_live_output=self.__sc.log.loglevel==LogLevel.Debug)
1472
+ arguments_for_log=arguments
1473
+ self.__sc.run_program_with_retry("docker",arguments,test_service_folder,arguments_for_log=arguments_for_log,print_live_output=self.__sc.log.loglevel==LogLevel.Debug)
1445
1474
 
1446
1475
  def load_deb_control_file_content(self, file: str, codeunitname: str, codeunitversion: str, installedsize: int, maintainername: str, maintaineremail: str, description: str) -> str:
1447
1476
  content = GeneralUtilities.read_text_from_file(file)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ScriptCollection
3
- Version: 4.2.69
3
+ Version: 4.2.70
4
4
  Summary: The ScriptCollection is the place for reusable scripts.
5
5
  Home-page: https://github.com/anionDev/ScriptCollection
6
6
  Author: Marius Göcke
@@ -1,7 +1,7 @@
1
1
  ScriptCollection/AnionBuildPlatform.py,sha256=K-PHarX802A0PU8uRu0GNcEZiXujFoXHACe-X9YJsAQ,11711
2
2
  ScriptCollection/CertificateUpdater.py,sha256=Pa6eyjQSx7IIvj4PQVMI0IwMs01KQrNSB7Qa-7lRfBs,9375
3
3
  ScriptCollection/Executables.py,sha256=qpo0g5peWdlK5uLIUCyLDB9c3JCk0ETbtmOJXZwuHh4,44510
4
- ScriptCollection/GeneralUtilities.py,sha256=FEjJEfA3riVT7G4sL8bzKPb7w0SN8YjONNWMtiBo_j8,64882
4
+ ScriptCollection/GeneralUtilities.py,sha256=3Fgp0fAXF-rfcohy6k1RsRcMXEVRF15fHl8QJnViKIg,65497
5
5
  ScriptCollection/HTTPMaintenanceOverheadHelper.py,sha256=TToNtyO1XzsMbBsTBf3o0xgOK0v4Jf03qw2Z0xb2nCk,2007
6
6
  ScriptCollection/ProcessesRunner.py,sha256=o5raxIt3lknNPoPrjNzJ2bprRPJ3SnL0rrR7crraD7E,1523
7
7
  ScriptCollection/ProgramRunnerBase.py,sha256=4A2eQgSg_rRgQcgSi-LYtUlM-uSQEpS7qFWn0tWt4uo,2171
@@ -9,7 +9,7 @@ ScriptCollection/ProgramRunnerMock.py,sha256=uTu-aFle1W_oKjeQEmuPsFPQpvo0kRf2FrR
9
9
  ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
10
10
  ScriptCollection/ProgramRunnerSudo.py,sha256=_khC3xuTdrPoLluBJZWfldltmmuKltABJPcbjZSFW-4,4835
11
11
  ScriptCollection/SCLog.py,sha256=8TRy1LeYMsPOIuWUcnUNNbO5pd-cNBS-3cn-kdzP8FU,4768
12
- ScriptCollection/ScriptCollectionCore.py,sha256=EKRyDmNi9sTTRbbsb6j-MEux0qKMiU_-UyH2xlJK2Vw,177453
12
+ ScriptCollection/ScriptCollectionCore.py,sha256=lVRgY6YA3UPwYXuuFZ9IjlwW-C-_s-ENT3K7s2_5FwU,180421
13
13
  ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  ScriptCollection/OCIImages/AbstractImageHandler.py,sha256=83qDMILwxhH9DbC0sb358Vu8PXEysmJJyap_6gECZqs,1627
15
15
  ScriptCollection/OCIImages/OCIImageManager.py,sha256=aBogkSXNDyi8NO11N-s03nuFJEv7PyJ-wjHuYYeZfvs,6662
@@ -22,33 +22,33 @@ ScriptCollection/OCIImages/ConcreteImageHandlers/__init__.py,sha256=47DEQpj8HBSa
22
22
  ScriptCollection/Resources/CultureChooser/CultureChooser.js,sha256=5-4pwGDq5j1UnpTZy850ZMoxlM9tYPeu781QpZBtCWM,951
23
23
  ScriptCollection/Resources/CultureChooser/index.html,sha256=gxQzbrSp4WU52TqN-gcBEtz2gJXmmM14OwTSFtFVRvw,276
24
24
  ScriptCollection/Resources/MaintenanceSite/MaintenanceSite.html,sha256=CX9S1bdOz6xU2aGfr03tJRGczQrlpn-IeODc15d5kc0,232
25
- ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py,sha256=xpt-Z_jztEaKgpT1DDSX7wezWX0VKS5LQb7IKAzvi4U,27860
25
+ ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py,sha256=EMNDgkUem87aH1csz7eoSBBEKkiZMLZqZhnxKSPQWe0,27845
26
26
  ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py,sha256=MieeAAKm1y58qXp1cCUN5mj5vwpq4Pc1uusUjPQzpvc,8237
27
- ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py,sha256=k2uurDeCDdeS0PGu6UJ0BIM2wSZFM0WEHx-1IwQrqO8,15407
27
+ ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py,sha256=8vVSVXlLxu8xct-5vISOJ7dJlsNnnAcwBzCb59PEY6k,15520
28
28
  ScriptCollection/TFCPS/TFCPS_CreateRelease.py,sha256=yqGstRjRfVVGbqrcBgtYStqth2x2SvBb3y2Ht8GsuMQ,6554
29
29
  ScriptCollection/TFCPS/TFCPS_Generic.py,sha256=O-0guM_LJCcZmPZJhMgTvXD2RXUJEBWWv6Bt6hDFhvM,1943
30
30
  ScriptCollection/TFCPS/TFCPS_MergeToMain.py,sha256=-Ev9D3bZDlUk2WFQhcmvzQ3FCS97OdsVUd0koAdmpZc,7474
31
31
  ScriptCollection/TFCPS/TFCPS_MergeToStable.py,sha256=Ajfy2pLajTuU6UpwItHt4C2a-gLF3gPc4z6BktL3Cio,22163
32
32
  ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py,sha256=f0Uq1cA_4LvmL72cal0crrbKF6PcxL13D9wBKuQ1YBw,2328
33
- ScriptCollection/TFCPS/TFCPS_Tools_General.py,sha256=9HhVAcCOHoqR8MG1aYdDWKW66qdsEclcdJkyvSJ9ikA,98448
33
+ ScriptCollection/TFCPS/TFCPS_Tools_General.py,sha256=H8qve4dwY6XjLAKrh8jAJohk8DGdtnqa_-frkrME8pU,100769
34
34
  ScriptCollection/TFCPS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
- ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py,sha256=zGTfn2Ytm7Y4W9Aj_R-f3hNMwYpErbF1lZWCPf3Gy8M,11893
35
+ ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py,sha256=sPO4Gf6oRbGH9QRA3p2nmTAeHtkyYr31ucLbJP09JeY,12139
36
36
  ScriptCollection/TFCPS/Docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py,sha256=bT6Gd5pQpZCw4OQz6HWkPCSn5z__eUUEisABLDSxd0o,200
38
38
  ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py,sha256=QyjOfMY22JWCvKjMelHiDWbJiWqotOfebpJpgDUaoO4,237
39
39
  ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py,sha256=i0zEGehj0sttxjjZtoq2KFSKp_ulxVyWp_ZgAhIY_So,241
40
40
  ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py,sha256=W957xFs4YBkWtU8q-JcbN4aWK2Aq8SIM1jePQRRbEkA,31993
41
41
  ScriptCollection/TFCPS/DotNet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
42
- ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py,sha256=U8oBAOLR2vJpVfc9631Rhb8a04nrnjUMMX-U7pvXjok,7342
42
+ ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py,sha256=KAjyFyEjpkghsVPskfsHD68k4Z92gRCT_q6BXfikRwE,7660
43
43
  ScriptCollection/TFCPS/Flutter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
44
  ScriptCollection/TFCPS/Go/TFCPS_CodeUnitSpecific_Go.py,sha256=kyx26AnT1-LySFA46wfJ9yZUKYdMWTD0U2XZfSQbuB0,3497
45
45
  ScriptCollection/TFCPS/Go/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py,sha256=5xIwcd1cDI1NDrbX5q9MVnnNLdl6PWDrZUO8xyqWjW8,12791
46
+ ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py,sha256=GQLE6FeR-XNRlLDwionndM-oGLPIbgNhSAx5rc3nnDY,12900
47
47
  ScriptCollection/TFCPS/NodeJS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
- ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py,sha256=KFKDdfV9DFHE5n7TI6m1Ra1Qw2JwL_JQjneBfqcRQ_w,13467
48
+ ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py,sha256=9XK7XnbeOnq_4siVoWovogStoKFiZLhGh3C_f2YaznI,13621
49
49
  ScriptCollection/TFCPS/Python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
- scriptcollection-4.2.69.dist-info/METADATA,sha256=ZaxTho_S3qjR3qE6XGSejld39Ve1DD7AMZ1KPtil_0w,7690
51
- scriptcollection-4.2.69.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
52
- scriptcollection-4.2.69.dist-info/entry_points.txt,sha256=27XwAJEcaMEc1be0Ec1vKHCbiU4Ziu8jKL-SqsrYOIQ,4680
53
- scriptcollection-4.2.69.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
54
- scriptcollection-4.2.69.dist-info/RECORD,,
50
+ scriptcollection-4.2.70.dist-info/METADATA,sha256=ZH8RQwQoInXomGWNzDd0_tMMN1WkGMhU1FfXG2YZ174,7690
51
+ scriptcollection-4.2.70.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
52
+ scriptcollection-4.2.70.dist-info/entry_points.txt,sha256=27XwAJEcaMEc1be0Ec1vKHCbiU4Ziu8jKL-SqsrYOIQ,4680
53
+ scriptcollection-4.2.70.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
54
+ scriptcollection-4.2.70.dist-info/RECORD,,