ScriptCollection 3.5.92__py3-none-any.whl → 3.5.93__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.
@@ -619,3 +619,12 @@ def NpmI() -> int:
619
619
  t = TasksForCommonProjectStructure()
620
620
  t.do_npm_install(folder, args.force, 3 if args.verbose else 0)
621
621
  return 0
622
+
623
+
624
+ def CurrentUserHasElevatedPrivileges() -> int:
625
+ parser = argparse.ArgumentParser(description="Returns 1 if the current user has elevated privileges. Otherwise this function returns 0.")
626
+ parser.parse_args()
627
+ if GeneralUtilities.current_user_has_elevated_privileges():
628
+ return 1
629
+ else:
630
+ return 0
@@ -348,29 +348,60 @@ class GeneralUtilities:
348
348
  @staticmethod
349
349
  @check_arguments
350
350
  def ends_with_newline_character(content: bytes) -> bool:
351
- return content.endswith(b'\x0a')
351
+ result = content.endswith(GeneralUtilities.string_to_bytes("\n"))
352
+ return result
352
353
 
353
354
  @staticmethod
354
355
  @check_arguments
355
- def __get_new_line_character_if_required(file: str) -> bool:
356
+ def file_ends_with_content(file: str) -> bool:
356
357
  content = GeneralUtilities.read_binary_from_file(file)
357
358
  if len(content) == 0:
358
- return ""
359
+ return False
359
360
  else:
360
361
  if GeneralUtilities.ends_with_newline_character(content):
361
- return ""
362
+ return False
362
363
  else:
363
- return "\n"
364
+ return True
365
+
366
+ @staticmethod
367
+ @check_arguments
368
+ def get_new_line_character_for_textfile_if_required(file: str) -> bool:
369
+ if GeneralUtilities.file_ends_with_content(file):
370
+ return "\n"
371
+ else:
372
+ return ""
364
373
 
365
374
  @staticmethod
366
375
  @check_arguments
367
376
  def append_line_to_file(file: str, line: str, encoding: str = "utf-8") -> None:
368
- line = GeneralUtilities.__get_new_line_character_if_required(file)+line
369
- GeneralUtilities.append_to_file(file, line, encoding)
377
+ GeneralUtilities.append_lines_to_file(file, [line], encoding)
378
+
379
+ @staticmethod
380
+ @check_arguments
381
+ def append_lines_to_file(file: str, lines: list[str], encoding: str = "utf-8") -> None:
382
+ if len(lines) == 0:
383
+ return
384
+ is_first_line = True
385
+ for line in lines:
386
+ insert_linebreak: bool
387
+ if is_first_line:
388
+ insert_linebreak = GeneralUtilities.file_ends_with_content(file)
389
+ else:
390
+ insert_linebreak = True
391
+ line_to_write: str = None
392
+ if insert_linebreak:
393
+ line_to_write = "\n"+line
394
+ else:
395
+ line_to_write = line
396
+ with open(file, "r+b") as fileObject:
397
+ fileObject.seek(0, os.SEEK_END)
398
+ fileObject.write(GeneralUtilities.string_to_bytes(line_to_write, encoding))
399
+ is_first_line = False
370
400
 
371
401
  @staticmethod
372
402
  @check_arguments
373
403
  def append_to_file(file: str, content: str, encoding: str = "utf-8") -> None:
404
+ GeneralUtilities.assert_condition(not "\n" in content, "Appending multiple lines is not allowed. Use append_lines_to_file instead.")
374
405
  with open(file, "a", encoding=encoding) as fileObject:
375
406
  fileObject.write(content)
376
407
 
@@ -508,6 +539,11 @@ class GeneralUtilities:
508
539
  def read_lines_from_file(file: str, encoding="utf-8") -> list[str]:
509
540
  return [GeneralUtilities.strip_new_line_character(line) for line in GeneralUtilities.read_text_from_file(file, encoding).split('\n')]
510
541
 
542
+ @staticmethod
543
+ @check_arguments
544
+ def read_nonempty_lines_from_file(file: str, encoding="utf-8") -> list[str]:
545
+ return [line for line in GeneralUtilities.read_lines_from_file(file, encoding) if GeneralUtilities.string_has_content(line)]
546
+
511
547
  @staticmethod
512
548
  @check_arguments
513
549
  def read_text_from_file(file: str, encoding="utf-8") -> str:
@@ -960,20 +996,20 @@ class GeneralUtilities:
960
996
 
961
997
  @staticmethod
962
998
  @check_arguments
963
- def retry_action(action, amount_of_attempts: int,action_name:str=None) -> None:
999
+ def retry_action(action, amount_of_attempts: int, action_name: str = None) -> None:
964
1000
  amount_of_fails = 0
965
1001
  enabled = True
966
1002
  while enabled:
967
1003
  try:
968
- result=action()
1004
+ result = action()
969
1005
  return result
970
1006
  except Exception:
971
1007
  amount_of_fails = amount_of_fails+1
972
1008
  GeneralUtilities.assert_condition(not (amount_of_attempts < amount_of_fails))
973
1009
  if amount_of_fails == amount_of_attempts:
974
- message=f"Action failed {amount_of_attempts} times."
1010
+ message = f"Action failed {amount_of_attempts} times."
975
1011
  if action_name is not None:
976
- message=f"{message} Name of action: {action_name}"
1012
+ message = f"{message} Name of action: {action_name}"
977
1013
  GeneralUtilities.write_message_to_stderr(message)
978
1014
  raise
979
1015
  return None
@@ -0,0 +1,2 @@
1
+ class SCLog:
2
+ pass # TODO
@@ -32,7 +32,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
32
32
  from .ProgramRunnerPopen import ProgramRunnerPopen
33
33
  from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
34
34
 
35
- version = "3.5.92"
35
+ version = "3.5.93"
36
36
  __version__ = version
37
37
 
38
38
 
@@ -2109,8 +2109,7 @@ TXDX
2109
2109
 
2110
2110
  ## Deployment-proecsses
2111
2111
 
2112
- TXDX
2113
- """)
2112
+ TXDX""")
2114
2113
  self.__add_chapter(main_reference_file, reference_content_folder, 8, 'Crosscutting Concepts', """TXDX""")
2115
2114
  self.__add_chapter(main_reference_file, reference_content_folder, 9, 'Architectural Decisions', """## Decision-board
2116
2115
 
@@ -759,6 +759,7 @@ class TasksForCommonProjectStructure:
759
759
  target = f"{codeunit_folder}\\{bomfile_folder}\\{codeunit_name}.{codeunitversion}.sbom.xml"
760
760
  GeneralUtilities.ensure_file_does_not_exist(target)
761
761
  os.rename(f"{codeunit_folder}\\{bomfile_folder}\\bom.xml", target)
762
+ # TODO format the sbom.xml-file
762
763
 
763
764
  @GeneralUtilities.check_arguments
764
765
  def standardized_tasks_run_linting_for_flutter_project_in_common_project_structure(self, script_file: str, default_verbosity: int, args: list[str]):
@@ -1338,6 +1339,28 @@ class TasksForCommonProjectStructure:
1338
1339
  @GeneralUtilities.check_arguments
1339
1340
  def standardized_tasks_build_for_docker_project(self, build_script_file: str, target_environment_type: str, verbosity: int, commandline_arguments: list[str]) -> None:
1340
1341
  self.standardized_tasks_build_for_docker_project_with_additional_build_arguments(build_script_file, target_environment_type, verbosity, commandline_arguments, dict[str, str]())
1342
+ self.generate_sbom_for_docker_image(build_script_file, verbosity, commandline_arguments)
1343
+
1344
+ @GeneralUtilities.check_arguments
1345
+ def merge_sbom_file_from_dependent_codeunit_into_this(self, build_script_file: str, dependent_codeunit_name: str) -> None:
1346
+ codeunitname: str = Path(os.path.dirname(build_script_file)).parent.parent.name
1347
+ codeunit_folder = GeneralUtilities.resolve_relative_path("../..", str(os.path.dirname(build_script_file)))
1348
+ repository_folder = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
1349
+ dependent_codeunit_folder = os.path.join(repository_folder, dependent_codeunit_name).replace("\\", "/")
1350
+ t = TasksForCommonProjectStructure()
1351
+ sbom_file = f"{codeunitname}/Other/Artifacts/BOM/{codeunitname}.{t.get_version_of_codeunit_folder(codeunit_folder)}.sbom.xml"
1352
+ dependent_sbom_file = f"{dependent_codeunit_name}/Other/Artifacts/BOM/{dependent_codeunit_name}.{t.get_version_of_codeunit_folder(dependent_codeunit_folder)}.sbom.xml"
1353
+ self.merge_sbom_file(repository_folder, dependent_sbom_file, sbom_file)
1354
+
1355
+ @GeneralUtilities.check_arguments
1356
+ def merge_sbom_file(self, repository_folder: str, source_sbom_file: str, target_sbom_file: str) -> None:
1357
+ GeneralUtilities.assert_file_exists(os.path.join(repository_folder, source_sbom_file))
1358
+ GeneralUtilities.assert_file_exists(os.path.join(repository_folder, target_sbom_file))
1359
+ target_original_sbom_file = os.path.dirname(target_sbom_file)+"/"+os.path.basename(target_sbom_file)+".original.xml"
1360
+ os.rename(os.path.join(repository_folder, target_sbom_file), os.path.join(repository_folder, target_original_sbom_file))
1361
+ ScriptCollectionCore().run_program("docker", f"run --rm -v {repository_folder}:/Repository cyclonedx/cyclonedx-cli merge --input-files /Repository/{source_sbom_file} /Repository/{target_original_sbom_file} --output-file /Repository/{target_sbom_file}")
1362
+ GeneralUtilities.ensure_file_does_not_exist(os.path.join(repository_folder, target_original_sbom_file))
1363
+ # TODO format the sbom.xml-file
1341
1364
 
1342
1365
  @GeneralUtilities.check_arguments
1343
1366
  def standardized_tasks_build_for_docker_project_with_additional_build_arguments(self, build_script_file: str, target_environment_type: str, verbosity: int, commandline_arguments: list[str], custom_arguments: dict[str, str]) -> None:
@@ -1377,6 +1400,7 @@ class TasksForCommonProjectStructure:
1377
1400
  codeunitversion = self.get_version_of_codeunit(os.path.join(codeunit_folder, f"{codeunitname}.codeunit.xml"))
1378
1401
  GeneralUtilities.ensure_directory_exists(sbom_folder)
1379
1402
  self.__sc.run_program_argsasarray("docker", ["sbom", "--format", "cyclonedx", f"{codeunitname_lower}:{codeunitversion}", "--output", f"{codeunitname}.{codeunitversion}.sbom.xml"], sbom_folder, verbosity=verbosity, print_errors_as_information=True)
1403
+ # TODO format the sbom.xml-file
1380
1404
 
1381
1405
  @GeneralUtilities.check_arguments
1382
1406
  def push_docker_build_artifact(self, push_artifacts_file: str, registry: str, verbosity: int, push_readme: bool, commandline_arguments: list[str], repository_folder_name: str) -> None:
@@ -1527,6 +1551,8 @@ class TasksForCommonProjectStructure:
1527
1551
  author_emailaddress = expected_author.xpath('./cps:developeremailaddress/text()', namespaces=namespaces)[0]
1528
1552
  expected_authors.append((author_name, author_emailaddress))
1529
1553
  actual_authors: list[tuple[str, str]] = self.__sc.get_all_authors_and_committers_of_repository(repository_folder, codeunit_name, verbosity)
1554
+ # TODO refactor this check to only check commits which are behind this but which are not already on main
1555
+ # TODO verify also if the commit is signed by a valid key of the author
1530
1556
  for actual_author in actual_authors:
1531
1557
  if not (actual_author) in expected_authors:
1532
1558
  actual_author_formatted = f"{actual_author[0]} <{actual_author[1]}>"
@@ -1704,7 +1730,8 @@ class TasksForCommonProjectStructure:
1704
1730
  def standardized_tasks_build_bom_for_node_project(self, codeunit_folder: str, verbosity: int, commandline_arguments: list[str]) -> None:
1705
1731
  self.assert_is_codeunit_folder(codeunit_folder)
1706
1732
  verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
1707
- # TODO
1733
+ self.run_with_epew("cyclonedx-npm", f"--output-format xml --output-file Other/Artifacts/BOM/{os.path.basename(codeunit_folder)}.{self.get_version_of_codeunit_folder(codeunit_folder)}.sbom.xml", codeunit_folder, verbosity=verbosity)
1734
+ # TODO format the sbom.xml-file
1708
1735
 
1709
1736
  @GeneralUtilities.check_arguments
1710
1737
  def standardized_tasks_linting_for_angular_codeunit(self, linting_script_file: str, verbosity: int, build_environment_target_type: str, commandline_arguments: list[str]) -> None:
@@ -2564,6 +2591,8 @@ class TasksForCommonProjectStructure:
2564
2591
  security_txt_file = GeneralUtilities.resolve_relative_path(security_txt_file_relative, repository_folder)
2565
2592
  if not os.path.isfile(security_txt_file):
2566
2593
  raise ValueError(f"The repository does not contain a '{security_txt_file_relative}'-file. See https://securitytxt.org/ for more information.")
2594
+ # TODO throw error if the date set in the file is expired
2595
+ # TODO write wartning if the date set in the file expires soon
2567
2596
 
2568
2597
  @GeneralUtilities.check_arguments
2569
2598
  def __check_for_staged_or_committed_ignored_files(self, repository_folder: str) -> None:
@@ -2689,12 +2718,48 @@ class TasksForCommonProjectStructure:
2689
2718
  def generate_svg_files_from_plantuml_files(self, target_folder: str) -> None:
2690
2719
  self.ensure_plantuml_is_available(target_folder)
2691
2720
  plant_uml_folder = os.path.join(target_folder, "Other", "Resources", "PlantUML")
2692
- files_folder = os.path.join(target_folder, "Other", "Reference")
2721
+ files_folder = os.path.join(target_folder, "Other", "Resources", "Reference")
2693
2722
  sc = ScriptCollectionCore()
2694
2723
  for file in GeneralUtilities.get_all_files_of_folder(files_folder):
2695
2724
  if file.endswith(".plantuml"):
2696
2725
  argument = ['-jar', f'{plant_uml_folder}/plantuml.jar', os.path.basename(file).replace("\\", "/"), '-tsvg']
2697
2726
  sc.run_program_argsasarray("java", argument, os.path.dirname(file), verbosity=0)
2727
+ # TODO format content of file
2728
+
2729
+ @GeneralUtilities.check_arguments
2730
+ def generate_codeunits_overview_diagram(self, repository_folder: str) -> None:
2731
+ self.__sc.assert_is_git_repository(repository_folder)
2732
+ project_name: str = os.path.basename(repository_folder)
2733
+ target_folder = os.path.join(repository_folder, "Other", "Resources", "Reference", "Technical", "Diagrams")
2734
+ GeneralUtilities.ensure_directory_exists(target_folder)
2735
+ target_file = os.path.join(target_folder, "CodeUnits-Overview.plantuml")
2736
+ lines = ["@startuml CodeUnits-Overview"]
2737
+ lines.append(f"title CodeUnits of {project_name}")
2738
+
2739
+ codeunits = self.get_codeunits(repository_folder)
2740
+ for codeunitname in codeunits:
2741
+ codeunit_file: str = os.path.join(repository_folder, codeunitname, f"{codeunitname}.codeunit.xml")
2742
+
2743
+ description = self.get_codeunit_description(codeunit_file)
2744
+
2745
+ lines.append(f"")
2746
+ lines.append(f"[{codeunitname}]")
2747
+ lines.append(f"note as {codeunitname}Note")
2748
+ lines.append(f" {description}")
2749
+ lines.append(f"end note")
2750
+ lines.append(f"{codeunitname} .. {codeunitname}Note")
2751
+
2752
+ lines.append(f"")
2753
+ for codeunitname in codeunits:
2754
+ codeunit_file: str = os.path.join(repository_folder, codeunitname, f"{codeunitname}.codeunit.xml")
2755
+ dependent_codeunits = self.get_dependent_code_units(codeunit_file)
2756
+ for dependent_codeunit in dependent_codeunits:
2757
+ lines.append(f"{codeunitname} --> {dependent_codeunit}")
2758
+
2759
+ lines.append(f"")
2760
+ lines.append("@enduml")
2761
+
2762
+ GeneralUtilities.write_lines_to_file(target_file, lines)
2698
2763
 
2699
2764
  @GeneralUtilities.check_arguments
2700
2765
  def load_deb_control_file_content(self, file: str, codeunitname: str, codeunitversion: str, installedsize: int, maintainername: str, maintaineremail: str, description: str,) -> str:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ScriptCollection
3
- Version: 3.5.92
3
+ Version: 3.5.93
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
@@ -33,7 +33,7 @@ Requires-Dist: ntplib>=0.4.0
33
33
  Requires-Dist: Pillow>=11.1.0
34
34
  Requires-Dist: pycdlib>=1.14.0
35
35
  Requires-Dist: Pygments>=2.19.1
36
- Requires-Dist: pylint>=3.3.4
36
+ Requires-Dist: pylint>=3.3.5
37
37
  Requires-Dist: pyOpenSSL>=25.0.0
38
38
  Requires-Dist: PyPDF>=5.3.1
39
39
  Requires-Dist: pytest>=8.3.5
@@ -0,0 +1,17 @@
1
+ ScriptCollection/Executables.py,sha256=HI9Pxs5Z9QxPGyqeJU2lWslEggFyGYANCqYVQZp6eJ0,30490
2
+ ScriptCollection/GeneralUtilities.py,sha256=q0ikIwmhklCFsaaj9YGPGdrNonibuRmWofvbwOtlxdM,42246
3
+ ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
4
+ ScriptCollection/ProgramRunnerBase.py,sha256=2kMIAqdc65UjBAddOZkzy_aFx9h5roZ5a4bQNM6RV6Y,2480
5
+ ScriptCollection/ProgramRunnerEpew.py,sha256=4pjEd0r9Fcz3TTDv0MdTSd5KkigYXcWUVI1X43regfU,6477
6
+ ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
7
+ ScriptCollection/RPStream.py,sha256=NRRHL3YSP3D9MuAV2jB_--0KUKCsvJGxeKnxgrRZ9kY,1545
8
+ ScriptCollection/SCLog.py,sha256=l4aekBiGoNkKGtvO_Er3NY_K7ts4ZWtIGlhq07I-4LY,30
9
+ ScriptCollection/ScriptCollectionCore.py,sha256=IGIu5wl1wm25-KnLo7MLOaNFkVZuQjEr69PGHxkCFGg,123625
10
+ ScriptCollection/TasksForCommonProjectStructure.py,sha256=UICi0p_m_uGOLP3c-Rk-dCxN0IzXIM0O_FwwRGNoHCM,221680
11
+ ScriptCollection/UpdateCertificates.py,sha256=Eynbgu7k9jLxApP2D_8Il77B6BFjJap6K7oTeEAZYbk,7790
12
+ ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ scriptcollection-3.5.93.dist-info/METADATA,sha256=USfCKrvr35eIM7vkEptzfc9tbnXP1IGw7D2dluFS5dA,7664
14
+ scriptcollection-3.5.93.dist-info/WHEEL,sha256=EaM1zKIUYa7rQnxGiOCGhzJABRwy4WO57rWMR3_tj4I,91
15
+ scriptcollection-3.5.93.dist-info/entry_points.txt,sha256=fYCGWGNGijBQHhFe6UAO-BEpfEOxLyNJemukt5ElSzs,3644
16
+ scriptcollection-3.5.93.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
17
+ scriptcollection-3.5.93.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.2)
2
+ Generator: setuptools (75.9.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -14,6 +14,7 @@ sccreatefolder = ScriptCollection.Executables:CreateFolder
14
14
  sccreatehashofallfiles = ScriptCollection.Executables:CreateHashOfAllFiles
15
15
  sccreateisofilewithobfuscatedfiles = ScriptCollection.Executables:CreateISOFileWithObfuscatedFiles
16
16
  sccreatesimplemergewithoutrelease = ScriptCollection.Executables:CreateSimpleMergeWithoutRelease
17
+ sccurrentuserhaselevatedprivileges = ScriptCollection.Executables:CurrentUserHasElevatedPrivileges
17
18
  scextractpdfpages = ScriptCollection.Executables:ExtractPDFPages
18
19
  scfilecontainscontent = ScriptCollection.Executables:FileContainsContent
19
20
  scfileexists = ScriptCollection.Executables:FileExists
@@ -1,16 +0,0 @@
1
- ScriptCollection/Executables.py,sha256=ApfwgRftLeG1NBpv7Jad98Yb-wI8sKjhtoIsxMmfGVY,30167
2
- ScriptCollection/GeneralUtilities.py,sha256=VVbbGFD4qLwWV211-E-n3faP2fZGc8mOBlKLd0oKHl4,40765
3
- ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
4
- ScriptCollection/ProgramRunnerBase.py,sha256=2kMIAqdc65UjBAddOZkzy_aFx9h5roZ5a4bQNM6RV6Y,2480
5
- ScriptCollection/ProgramRunnerEpew.py,sha256=4pjEd0r9Fcz3TTDv0MdTSd5KkigYXcWUVI1X43regfU,6477
6
- ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
7
- ScriptCollection/RPStream.py,sha256=NRRHL3YSP3D9MuAV2jB_--0KUKCsvJGxeKnxgrRZ9kY,1545
8
- ScriptCollection/ScriptCollectionCore.py,sha256=Qyo5uuSsVQIbwWxqGgyfetyVrZ2KO1yg_PlICIavTto,123626
9
- ScriptCollection/TasksForCommonProjectStructure.py,sha256=YWHvLc91WuCrmay9qqf43onRhYy94nbd1sKLiBfNrZ4,217137
10
- ScriptCollection/UpdateCertificates.py,sha256=Eynbgu7k9jLxApP2D_8Il77B6BFjJap6K7oTeEAZYbk,7790
11
- ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- scriptcollection-3.5.92.dist-info/METADATA,sha256=lsBwVdHT7ePQ2yjnuj-kq7uX7NVvVniSWodbiPdMJzs,7664
13
- scriptcollection-3.5.92.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
14
- scriptcollection-3.5.92.dist-info/entry_points.txt,sha256=1jAL5AuB8mvdw2v-6E7wCZFThurQxchiQynL8DCi-Yg,3545
15
- scriptcollection-3.5.92.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
16
- scriptcollection-3.5.92.dist-info/RECORD,,