ScriptCollection 4.0.42__py3-none-any.whl → 4.0.44__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.
@@ -37,7 +37,7 @@ from .ProgramRunnerPopen import ProgramRunnerPopen
37
37
  from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
38
38
  from .SCLog import SCLog, LogLevel
39
39
 
40
- version = "4.0.42"
40
+ version = "4.0.44"
41
41
  __version__ = version
42
42
 
43
43
 
@@ -2473,7 +2473,7 @@ OCR-content:
2473
2473
  def get_lines_of_code(self, repository: str, excluded_pattern: list[str]) -> int:
2474
2474
  self.assert_is_git_repository(repository)
2475
2475
  result: int = 0
2476
- self.log.log(f"Calculate lines of code in repository '{repository}' with excluded patterns: {', '.join(excluded_pattern)}")
2476
+ self.log.log(f"Calculate lines of code in repository '{repository}' with excluded patterns: {', '.join(excluded_pattern)}",LogLevel.Debug)
2477
2477
  git_response = self.run_program("git", "ls-files", repository)
2478
2478
  files: list[str] = GeneralUtilities.string_to_lines(git_response[1])
2479
2479
  for file in files:
@@ -2509,3 +2509,20 @@ OCR-content:
2509
2509
  file_path = os.path.join(root, file)
2510
2510
  arcname = os.path.relpath(file_path, start=folder)
2511
2511
  zipf.write(file_path, arcname)
2512
+
2513
+ @GeneralUtilities.check_arguments
2514
+ def start_local_test_service(self, file: str):
2515
+ example_folder = os.path.dirname(file)
2516
+ docker_compose_file = os.path.join(example_folder, "docker-compose.yml")
2517
+ for service in self.get_services_from_yaml_file(docker_compose_file):
2518
+ self.kill_docker_container(service)
2519
+ example_name = os.path.basename(example_folder)
2520
+ title = f"Test{example_name}"
2521
+ self.run_program("docker", f"compose -p {title.lower()} up --detach", example_folder, title=title)
2522
+
2523
+ @GeneralUtilities.check_arguments
2524
+ def stop_local_test_service(self, file: str):
2525
+ example_folder = os.path.dirname(file)
2526
+ example_name = os.path.basename(example_folder)
2527
+ title = f"Test{example_name}"
2528
+ self.run_program("docker", f"compose -p {title.lower()} down", example_folder, title=title)
@@ -427,11 +427,11 @@ class TFCPS_CodeUnitSpecific_DotNet_Functions(TFCPS_CodeUnitSpecific_Base):
427
427
  GeneralUtilities.ensure_directory_exists(temp_folder)
428
428
  runsettings_file = "runsettings.xml"
429
429
  codeunit_folder = f"{repository_folder}/{codeunit_name}"
430
- arg = f"test . -c {dotnet_build_configuration} -o {temp_folder}"
430
+ arg = f"test . -c {dotnet_build_configuration}"
431
431
  if os.path.isfile(os.path.join(codeunit_folder, runsettings_file)):
432
432
  arg = f"{arg} --settings {runsettings_file}"
433
433
  arg = f"{arg} /p:CollectCoverage=true /p:CoverletOutput=../Other/Artifacts/TestCoverage/Testcoverage /p:CoverletOutputFormat=cobertura"
434
- self._protected_sc.run_program("dotnet", arg, codeunit_folder, print_live_output=True)
434
+ test_run_result=self._protected_sc.run_program("dotnet", arg, codeunit_folder, print_live_output=True)#pylint:disable=unused-variable
435
435
  target_file = os.path.join(coverage_file_folder, "TestCoverage.xml")
436
436
  GeneralUtilities.ensure_file_does_not_exist(target_file)
437
437
  os.rename(os.path.join(coverage_file_folder, "Testcoverage.cobertura.xml"), target_file)
@@ -1,3 +1,7 @@
1
+ import os
2
+ import shutil
3
+ import re
4
+ import zipfile
1
5
  from ...GeneralUtilities import GeneralUtilities
2
6
  from ...SCLog import LogLevel
3
7
  from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
@@ -9,8 +13,62 @@ class TFCPS_CodeUnitSpecific_Flutter_Functions(TFCPS_CodeUnitSpecific_Base):
9
13
 
10
14
 
11
15
  @GeneralUtilities.check_arguments
12
- def build(self) -> None:
13
- pass#TODO
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
+ #TODO check for updateable dependencies (in a unified way)
14
72
 
15
73
  @GeneralUtilities.check_arguments
16
74
  def linting(self) -> None:
@@ -29,9 +87,31 @@ class TFCPS_CodeUnitSpecific_Flutter_Functions(TFCPS_CodeUnitSpecific_Base):
29
87
  pass#TODO
30
88
 
31
89
  @GeneralUtilities.check_arguments
32
- def run_testcases(self) -> None:
33
- pass#TODO
90
+ def run_testcases(self,package_name:str) -> None:
91
+ codeunit_folder = self.get_codeunit_folder()
92
+ repository_folder = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
93
+ codeunit_name = os.path.basename(codeunit_folder)
94
+ src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder)
95
+
96
+ self._protected_sc.run_with_epew("flutter", "test --coverage", src_folder)
97
+ test_coverage_folder_relative = "Other/Artifacts/TestCoverage"
98
+ test_coverage_folder = GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
99
+ GeneralUtilities.ensure_directory_exists(test_coverage_folder)
100
+ coverage_file_relative = f"{test_coverage_folder_relative}/TestCoverage.xml"
101
+ coverage_file = GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
102
+ self._protected_sc.run_with_epew("lcov_cobertura", f"coverage/lcov.info --base-dir . --excludes test --output ../{coverage_file_relative} --demangle", src_folder)
34
103
 
104
+ # format correctly
105
+ content = GeneralUtilities.read_text_from_file(coverage_file)
106
+ content = re.sub('<![^<]+>', '', content)
107
+ content = re.sub('\\\\', '/', content)
108
+ content = re.sub('\\ name=\\"lib\\"', '', content)
109
+ content = re.sub('\\ filename=\\"lib/', f' filename="{package_name}/lib/', content)
110
+ GeneralUtilities.write_text_to_file(coverage_file, content)
111
+ self.tfcps_Tools_General.merge_packages(coverage_file, self.get_codeunit_name())
112
+ self.tfcps_Tools_General.calculate_entire_line_rate(coverage_file)
113
+ self.run_testcases_common_post_task(repository_folder, codeunit_name, True, self.get_target_environment_type())
114
+
35
115
  class TFCPS_CodeUnitSpecific_Flutter_CLI:
36
116
 
37
117
  @staticmethod
@@ -369,7 +369,7 @@ class TFCPS_CodeUnitSpecific_Base(ABC):
369
369
  found_existing_files = True
370
370
  else:
371
371
  coverage_report_class.getparent().remove(coverage_report_class)
372
- GeneralUtilities.assert_condition(found_existing_files, f"No existing files in testcoderage-report-file \"{testcoveragefile}\".")
372
+ GeneralUtilities.assert_condition(found_existing_files, f"No existing files in testcoverage-report-file \"{testcoveragefile}\".")
373
373
  result = etree.tostring(root).decode("utf-8")
374
374
  GeneralUtilities.write_text_to_file(testcoveragefile, result)
375
375
 
@@ -28,6 +28,21 @@ class TFCPS_CodeUnit_BuildCodeUnits:
28
28
  self.additionalargumentsfile=additionalargumentsfile
29
29
  self.__is_pre_merge=is_pre_merge
30
30
 
31
+ @GeneralUtilities.check_arguments
32
+ def __save_lines_of_code(self, repository_folder: str, project_version: str) -> None:
33
+ loc = self.sc.get_lines_of_code_with_default_excluded_patterns(repository_folder)
34
+ loc_metric_folder = os.path.join(repository_folder, "Other", "Metrics")
35
+ GeneralUtilities.ensure_directory_exists(loc_metric_folder)
36
+ loc_metric_file = os.path.join(loc_metric_folder, "LinesOfCode.csv")
37
+ GeneralUtilities.ensure_file_exists(loc_metric_file)
38
+ old_lines = GeneralUtilities.read_lines_from_file(loc_metric_file)
39
+ new_lines = []
40
+ for line in old_lines:
41
+ if not line.startswith(f"v{project_version};"):
42
+ new_lines.append(line)
43
+ new_lines.append(f"v{project_version};{loc}")
44
+ GeneralUtilities.write_lines_to_file(loc_metric_file, new_lines)
45
+
31
46
  @GeneralUtilities.check_arguments
32
47
  def build_codeunits(self) -> None:
33
48
  self.sc.log.log(GeneralUtilities.get_line())
@@ -61,9 +76,6 @@ class TFCPS_CodeUnit_BuildCodeUnits:
61
76
  from_day = datetime(now.year, now.month, now.day, 0, 0, 0)
62
77
  self.tFCPS_Other.mark_current_version_as_supported(self.repository,project_version,from_day,until_day)
63
78
 
64
- #TODO search for secrets using TruffleHog
65
- #TODO run static code analysis tool to search for vulnerabilities
66
-
67
79
  codeunits:list[str]=self.tFCPS_Other.get_codeunits(self.repository)
68
80
  self.sc.log.log("Codeunits will be built in the following order:")
69
81
  for codeunit_name in codeunits:
@@ -72,10 +84,34 @@ class TFCPS_CodeUnit_BuildCodeUnits:
72
84
  tFCPS_CodeUnit_BuildCodeUnit:TFCPS_CodeUnit_BuildCodeUnit = TFCPS_CodeUnit_BuildCodeUnit(os.path.join(self.repository,codeunit_name),self.sc.log.loglevel,self.target_environment_type,self.additionalargumentsfile,self.use_cache(),self.is_pre_merge())
73
85
  self.sc.log.log(GeneralUtilities.get_line())
74
86
  tFCPS_CodeUnit_BuildCodeUnit.build_codeunit()
87
+
88
+ #TODO run static code analysis tool to search for vulnerabilities
89
+ self.__search_for_secrets()
90
+ self.__save_lines_of_code(self.repository,self.tFCPS_Other.get_version_of_project(self.repository))
91
+
75
92
  self.sc.log.log(GeneralUtilities.get_line())
76
93
  self.sc.log.log("Finished building codeunits.")
77
94
  self.sc.log.log(GeneralUtilities.get_line())
78
95
 
96
+ def __search_for_secrets(self):
97
+ exe_paths=self.tFCPS_Other.ensure_trufflehog_is_available()
98
+ exe_path:str=None
99
+ if GeneralUtilities.current_system_is_windows():
100
+ exe_path=exe_paths["Windows"]
101
+ elif GeneralUtilities.current_system_is_linux():
102
+ exe_path=exe_paths["Linux"]
103
+ else:
104
+ raise ValueError("unsupported")#TODO check for macos
105
+ result=self.sc.run_program(exe_path,"filesystem . --json",self.repository)
106
+
107
+ enabled:bool=False
108
+ if enabled:
109
+ self.sc.log.log("Secret-scan-result:")#TODO replace this by real analysis
110
+ for line in GeneralUtilities.string_to_lines(result[1]):
111
+ self.sc.log.log(line)
112
+ for line in GeneralUtilities.string_to_lines(result[2]):
113
+ self.sc.log.log(line,LogLevel.Error)
114
+
79
115
  @GeneralUtilities.check_arguments
80
116
  def use_cache(self) -> bool:
81
117
  return self.__use_cache
@@ -5,6 +5,7 @@ from pathlib import Path
5
5
  import shutil
6
6
  import zipfile
7
7
  import tarfile
8
+ import time
8
9
  import re
9
10
  import sys
10
11
  import json
@@ -61,15 +62,18 @@ class TFCPS_Tools_General:
61
62
  if not file_exists:
62
63
  self.__sc.log.log(f"Download Asset \"{githubuser}/{githubprojectname}: {resource_name}\" from GitHub to global cache...", LogLevel.Information)
63
64
  GeneralUtilities.ensure_folder_exists_and_is_empty(resource_folder)
64
- headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.96 Safari/537.36'}
65
+ headers = { 'User-Agent': 'Mozilla/5.0'}
65
66
  self.__add_github_api_key_if_available(headers)
66
67
  url = f"https://api.github.com/repos/{githubuser}/{githubprojectname}/releases/latest"
67
68
  self.__sc.log.log(f"Download \"{url}\"...", LogLevel.Debug)
69
+ time.sleep(2)
68
70
  response = requests.get(url, headers=headers, allow_redirects=True, timeout=(10, 10))
69
- latest_version = response.json()["tag_name"]
71
+ response_json=response.json()
72
+ latest_version = response_json["tag_name"]
70
73
  filename_on_github = get_filename_on_github(latest_version)
71
74
  link = f"https://github.com/{githubuser}/{githubprojectname}/releases/download/{latest_version}/{filename_on_github}"
72
- with requests.get(link, headers=headers, stream=True, allow_redirects=True, timeout=(5, 300)) as r:
75
+ time.sleep(2)
76
+ with requests.get(link, headers=headers, stream=True, allow_redirects=True, timeout=(5, 600)) as r:
73
77
  r.raise_for_status()
74
78
  total_size = int(r.headers.get("Content-Length", 0))
75
79
  downloaded = 0
@@ -555,6 +559,38 @@ class TFCPS_Tools_General:
555
559
  lines.append("@enduml")
556
560
 
557
561
  GeneralUtilities.write_lines_to_file(target_file, lines)
562
+
563
+ @GeneralUtilities.check_arguments
564
+ def ensure_trufflehog_is_available(self,enforce_update:bool=False) -> dict[str,str]:
565
+ def download_and_extract(osname: str, osname_in_github_asset: str, extension: str):
566
+ resource_name: str = f"TruffleHog_{osname}"
567
+ zip_filename: str = f"{resource_name}.{extension}"
568
+ target_folder_unextracted = os.path.join(self.get_global_cache_folder(),"Tools",resource_name+"_Unextracted")
569
+ target_folder_extracted = os.path.join(self.get_global_cache_folder(),"Tools",resource_name)
570
+ update:bool=not os.path.isdir(target_folder_extracted) or GeneralUtilities.folder_is_empty(target_folder_extracted) or enforce_update
571
+ if update:
572
+ downloaded_file=self.ensure_file_from_github_assets_is_available_with_retry(target_folder_unextracted, "trufflesecurity", "trufflehog", resource_name+"_Unextracted", zip_filename, lambda latest_version: f"trufflehog_{latest_version[1:]}_{osname_in_github_asset}_amd64.tar.gz",enforce_update=enforce_update)
573
+ #TODO add option to also download arm-version
574
+ local_zip_file: str = downloaded_file
575
+ GeneralUtilities.ensure_folder_exists_and_is_empty(target_folder_extracted)
576
+ if extension == "zip":
577
+ with zipfile.ZipFile(local_zip_file, 'r') as zip_ref:
578
+ zip_ref.extractall(target_folder_extracted)
579
+ elif extension == "tar.gz":
580
+ with tarfile.open(local_zip_file, "r:gz") as tar:
581
+ tar.extractall(path=target_folder_extracted)
582
+ else:
583
+ raise ValueError(f"Unknown extension: \"{extension}\"")
584
+ GeneralUtilities.ensure_directory_does_not_exist(target_folder_unextracted)
585
+ GeneralUtilities.assert_folder_exists(target_folder_extracted)
586
+ executable=[f for f in GeneralUtilities.get_all_files_of_folder(target_folder_extracted) if os.path.basename(f).startswith("trufflehog")][0]
587
+ return executable
588
+
589
+ result=dict[str,str]()
590
+ result["Windows"]=download_and_extract("Windows", "windows", "tar.gz")
591
+ result["Linux"]=download_and_extract("Linux", "linux", "tar.gz")
592
+ result["MacOS"]=download_and_extract("MacOS", "darwin", "tar.gz")
593
+ return result
558
594
 
559
595
  @GeneralUtilities.check_arguments
560
596
  def generate_tasksfile_from_workspace_file(self, repository_folder: str, append_cli_args_at_end: bool = False) -> None:
@@ -671,9 +707,9 @@ class TFCPS_Tools_General:
671
707
  if repository_subname is not None:
672
708
  target_folder = f"{resrepo_data_folder}/{repository_subname}"
673
709
 
674
- update:bool=GeneralUtilities.folder_is_empty(target_folder) or not use_cache
710
+ update:bool=not os.path.isdir(target_folder) or GeneralUtilities.folder_is_empty(target_folder) or not use_cache
675
711
  if update:
676
- self.__sc.run_program(f"Clone {remote_repository_link} as resource", LogLevel.Information)
712
+ self.__sc.log.log(f"Clone {remote_repository_link} as resource...", LogLevel.Information)
677
713
  GeneralUtilities.ensure_folder_exists_and_is_empty(target_folder)
678
714
  self.__sc.run_program("git", f"clone --recurse-submodules {remote_repository_link} {target_folder}")
679
715
  self.__sc.run_program("git", f"checkout {latest_version}", target_folder)
@@ -755,7 +791,7 @@ class TFCPS_Tools_General:
755
791
  @GeneralUtilities.check_arguments
756
792
  def do_npm_install(self, package_json_folder: str, npm_force: bool,use_cache:bool) -> None:
757
793
  target_folder:str=os.path.join(package_json_folder,"node_modules")
758
- update:bool=GeneralUtilities.folder_is_empty(target_folder) or GeneralUtilities.folder_is_empty(target_folder) or not use_cache
794
+ update:bool=not os.path.isdir(target_folder) or GeneralUtilities.folder_is_empty(target_folder) or not use_cache
759
795
  if update:
760
796
  self.__sc.log.log("Do npm-install...")
761
797
  argument1 = "install"
@@ -897,7 +933,7 @@ class TFCPS_Tools_General:
897
933
  GeneralUtilities.ensure_folder_exists_and_is_empty(target_folder)
898
934
  GeneralUtilities.copy_content_of_folder(source_folder, target_folder)
899
935
 
900
-
936
+
901
937
  @GeneralUtilities.check_arguments
902
938
  def merge_packages(self,coverage_file:str,package_name:str) -> None:
903
939
  tree = etree.parse(coverage_file)
@@ -906,7 +942,7 @@ class TFCPS_Tools_General:
906
942
  all_classes = []
907
943
  for pkg in packages:
908
944
  pkg_name:str=pkg.get("name")
909
- if pkg_name==package_name or pkg_name.startswith(f"{package_name}."):
945
+ if len(packages)==1 or ( pkg_name==package_name or pkg_name.startswith(f"{package_name}.")):
910
946
  classes = pkg.find("classes")
911
947
  if classes is not None:
912
948
  all_classes.extend(classes.findall("class"))
@@ -918,11 +954,11 @@ class TFCPS_Tools_General:
918
954
  packages_node.clear()
919
955
  packages_node.append(new_package)
920
956
  tree.write(coverage_file, pretty_print=True, xml_declaration=True, encoding="UTF-8")
921
- self.__calculate_entire_line_rate(coverage_file)
957
+ self.calculate_entire_line_rate(coverage_file)
922
958
 
923
959
 
924
960
  @GeneralUtilities.check_arguments
925
- def __calculate_entire_line_rate(self,coverage_file:str) -> None:
961
+ def calculate_entire_line_rate(self,coverage_file:str) -> None:
926
962
  tree = etree.parse(coverage_file)
927
963
  root = tree.getroot()
928
964
  package = root.find("./packages/package")
@@ -943,6 +979,7 @@ class TFCPS_Tools_General:
943
979
  package.set("line-rate", str(line_rate))
944
980
  tree.write(coverage_file, pretty_print=True, xml_declaration=True, encoding="UTF-8")
945
981
 
982
+
946
983
  @GeneralUtilities.check_arguments
947
984
  def generate_api_client_from_dependent_codeunit_for_angular(self, codeunit_folder:str, name_of_api_providing_codeunit: str, generated_program_part_name: str,language:str,use_cache:bool) -> None:
948
985
  target_subfolder_in_codeunit = f"src/app/generated/{generated_program_part_name}"
@@ -1150,3 +1187,22 @@ class TFCPS_Tools_General:
1150
1187
  self.__sc.run_program_with_retry("docker", f"push {remote_image_version}")
1151
1188
  if push_readme:
1152
1189
  self.__sc.run_program_with_retry("docker-pushrm", f"{remote_repo}", codeunit_folder)
1190
+
1191
+ def prepare_building_codeunits(self,repository_folder:str,use_cache:bool,generate_development_certificate:bool):
1192
+ if generate_development_certificate:
1193
+ self.ensure_certificate_authority_for_development_purposes_is_generated(repository_folder)
1194
+ self.generate_certificate_for_development_purposes_for_product(repository_folder)
1195
+ self.generate_tasksfile_from_workspace_file(repository_folder)
1196
+ self.generate_codeunits_overview_diagram(repository_folder)
1197
+ self.generate_svg_files_from_plantuml_files_for_repository(repository_folder,use_cache)
1198
+
1199
+ @GeneralUtilities.check_arguments
1200
+ def copy_product_resource_to_codeunit_resource_folder(self, codeunit_folder: str, resourcename: str) -> None:
1201
+ repository_folder = GeneralUtilities.resolve_relative_path(f"..", codeunit_folder)
1202
+ self.__sc.assert_is_git_repository(repository_folder)
1203
+ src_folder = GeneralUtilities.resolve_relative_path(f"Other/Resources/{resourcename}", repository_folder)
1204
+ GeneralUtilities.assert_condition(os.path.isdir(src_folder), f"Required product-resource {resourcename} does not exist. Expected folder: {src_folder}")
1205
+ trg_folder = GeneralUtilities.resolve_relative_path(f"Other/Resources/{resourcename}", codeunit_folder)
1206
+ GeneralUtilities.ensure_directory_does_not_exist(trg_folder)
1207
+ GeneralUtilities.ensure_directory_exists(trg_folder)
1208
+ GeneralUtilities.copy_content_of_folder(src_folder, trg_folder)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ScriptCollection
3
- Version: 4.0.42
3
+ Version: 4.0.44
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
@@ -9,34 +9,34 @@ ScriptCollection/ProgramRunnerEpew.py,sha256=TJdDx9zIMSiCaXh8X-ekrMlbXfGtmd0Mmyx
9
9
  ScriptCollection/ProgramRunnerMock.py,sha256=uTu-aFle1W_oKjeQEmuPsFPQpvo0kRf2FrRjAPIwT5Y,37
10
10
  ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
11
11
  ScriptCollection/SCLog.py,sha256=dxGOI4E9lG5v9jk_LajXCkM5nghliCDV8YB8Ihn160s,4541
12
- ScriptCollection/ScriptCollectionCore.py,sha256=AAOs9aHt-Wiq5ANkwmJ1Wd06O7zkgjRnpJGtVuW6TYI,141223
12
+ ScriptCollection/ScriptCollectionCore.py,sha256=XzWxKdyl8w0b5_7dBpu2Wiv52siu_jNjvRfWClQ2Rls,142113
13
13
  ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py,sha256=E7QtV1y5ZUFPO3Jfn04__KBRwOlOisB3Z0ByvMwc0rA,25853
14
+ ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py,sha256=2Ng-GyKWQ6FfTUmogd7g-xF6_XeTMxvkeJddagxFR5o,25853
15
15
  ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py,sha256=4rYKgTAga11NiDx8YUqz3K_Q4eX_n3kC6lvNdXEa24s,7389
16
- ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py,sha256=h3PWj7SgJF9huMognPpfNwGb9E9Y9HQ0Ym72yvvJwwg,5676
16
+ ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py,sha256=EH5yV33emYfbYqdikrPgW9UdF7UYV6rpBS1JGHNxA6M,7483
17
17
  ScriptCollection/TFCPS/TFCPS_CreateRelease.py,sha256=bcJlfI062Eoq7MOIhun-_iNG7SdO1ZIuC_cylaoLI1s,6332
18
18
  ScriptCollection/TFCPS/TFCPS_Generic.py,sha256=O-0guM_LJCcZmPZJhMgTvXD2RXUJEBWWv6Bt6hDFhvM,1943
19
19
  ScriptCollection/TFCPS/TFCPS_MergeToMain.py,sha256=41g219jaBRZ2VQCrWM4-Trvervrt8b5oATPwIIGNpag,7244
20
20
  ScriptCollection/TFCPS/TFCPS_MergeToStable.py,sha256=ifB1K6A903vvfH0LvtiFbZgYSgR94thfEI-jjf40LpU,21653
21
21
  ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py,sha256=CxdwUklhZVuJGp0vcokoH_KMXFzmlUlZwj77xFYijho,2242
22
22
  ScriptCollection/TFCPS/TFCPS_Tools_Dependencies.py,sha256=o7HI3ki3WWqlAiUsrh3Lky_w6UhYh9hdjYPGOhubQGA,414
23
- ScriptCollection/TFCPS/TFCPS_Tools_General.py,sha256=rG54XGperjNVIszLWa024_y3nwzmvxJIVKJKvHTOS8o,72541
23
+ ScriptCollection/TFCPS/TFCPS_Tools_General.py,sha256=ONdapcG29BCh1CwJR_8jHzll0W5QuyZ-EPJrxMcMIqU,76441
24
24
  ScriptCollection/TFCPS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py,sha256=-g8h2gCf9rh0KJXUBeQD5d0qLJgBU3Q8DNZXM1UXC04,5259
26
26
  ScriptCollection/TFCPS/Docker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py,sha256=bT6Gd5pQpZCw4OQz6HWkPCSn5z__eUUEisABLDSxd0o,200
28
28
  ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py,sha256=QyjOfMY22JWCvKjMelHiDWbJiWqotOfebpJpgDUaoO4,237
29
29
  ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py,sha256=i0zEGehj0sttxjjZtoq2KFSKp_ulxVyWp_ZgAhIY_So,241
30
- ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py,sha256=myR8hG2RMGg59S6Rf0Ts7R7df2IIVFDkazu4XSmSvrA,31001
30
+ ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py,sha256=ufeWuqtNOPAtEyHayxHGPdjiJsT0lxYR2gAWle9p7T4,31031
31
31
  ScriptCollection/TFCPS/DotNet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py,sha256=6g1xZ6_Nnr0Xa2VvSEtMg0H1hjUCvjzXXaPHFJ2xD1o,1626
32
+ ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py,sha256=TIR95f6TVOnW25ieX9q4RUi1FogbYEfrlZOcZ1aE014,6969
33
33
  ScriptCollection/TFCPS/Flutter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
34
  ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py,sha256=dnuDlQXThFmhe6EbUAWmGhx7AAYGL0lVUqsrhOgtmC8,6255
35
35
  ScriptCollection/TFCPS/NodeJS/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py,sha256=q7msAxCb5VIZ-xhFg1MfzUvWomQRKYldqmW42KFhyMU,6868
37
37
  ScriptCollection/TFCPS/Python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- scriptcollection-4.0.42.dist-info/METADATA,sha256=kh_TAqqZMV_maUDbD49VwhRkaTZo95zZWLAYAioznrE,7688
39
- scriptcollection-4.0.42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
- scriptcollection-4.0.42.dist-info/entry_points.txt,sha256=NeU26D6q7d8n2cmKQiOvHK21w1C7D2kxoNRJaKiyZ5w,4295
41
- scriptcollection-4.0.42.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
42
- scriptcollection-4.0.42.dist-info/RECORD,,
38
+ scriptcollection-4.0.44.dist-info/METADATA,sha256=DaIE8QIbw3p85KpjMgddKuS4AgEynTUTTauJD5LL8lo,7688
39
+ scriptcollection-4.0.44.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
+ scriptcollection-4.0.44.dist-info/entry_points.txt,sha256=RhfJxpWvSMIkdQ_1Pan1uXPTgYCTD1EcP0ZshkA2vtA,4366
41
+ scriptcollection-4.0.44.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
42
+ scriptcollection-4.0.44.dist-info/RECORD,,
@@ -56,6 +56,7 @@ scsetcontentoffile = ScriptCollection.Executables:SetContentOfFile
56
56
  scshow2faasqrcode = ScriptCollection.Executables:Show2FAAsQRCode
57
57
  scshowmissingfiles = ScriptCollection.Executables:ShowMissingFiles
58
58
  scsigncertificate = ScriptCollection.Executables:SignCertificate
59
+ scupdatedependencies = ScriptCollection.Executables:UpdateDependencies
59
60
  scupdateimagesindockercomposefile = ScriptCollection.Executables:UpdateImagesInDockerComposeFile
60
61
  scupdatenugetpackagesincsharpproject = ScriptCollection.Executables:UpdateNugetpackagesInCsharpProject
61
62
  scupdatetimestampinfile = ScriptCollection.Executables:UpdateTimestampInFile