ScriptCollection 3.5.65__py3-none-any.whl → 3.5.67__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.
@@ -553,7 +553,15 @@ def ListFolderContent() -> int:
553
553
  # TODO add option to also list transitively list subfolder
554
554
  # TODO add option to print only folder
555
555
  # TODO add option to print only files
556
- return 1
556
+ parser = argparse.ArgumentParser(description="This function lists folder-content.")
557
+ parser.add_argument('-p', '--path', required=True)
558
+ args=parser.parse_args()
559
+ folder=args.path
560
+ if not os.path.isabs(folder):
561
+ folder=GeneralUtilities.resolve_relative_path(folder,os.getcwd())
562
+ for file in GeneralUtilities.get_direct_files_of_folder(folder):
563
+ GeneralUtilities.write_message_to_stdout(file)
564
+ return 0
557
565
 
558
566
 
559
567
  def ForEach() -> int:
@@ -930,13 +930,14 @@ class GeneralUtilities:
930
930
  enabled = True
931
931
  while enabled:
932
932
  try:
933
- action()
934
- return
933
+ result=action()
934
+ return result
935
935
  except Exception:
936
936
  amount_of_fails = amount_of_fails+1
937
937
  GeneralUtilities.assert_condition(not (amount_of_attempts < amount_of_fails))
938
938
  if amount_of_fails == amount_of_attempts:
939
939
  raise
940
+ return None
940
941
 
941
942
  @staticmethod
942
943
  @check_arguments
@@ -16,6 +16,7 @@ from pathlib import Path
16
16
  from subprocess import Popen
17
17
  import re
18
18
  import shutil
19
+ from typing import IO
19
20
  import uuid
20
21
  import tempfile
21
22
  import io
@@ -31,7 +32,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
31
32
  from .ProgramRunnerPopen import ProgramRunnerPopen
32
33
  from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
33
34
 
34
- version = "3.5.65"
35
+ version = "3.5.67"
35
36
  __version__ = version
36
37
 
37
38
 
@@ -617,6 +618,21 @@ class ScriptCollectionCore:
617
618
  for renamed_item, original_name in renamed_items.items():
618
619
  os.rename(renamed_item, original_name)
619
620
 
621
+ @GeneralUtilities.check_arguments
622
+ def list_files(self, path: str) -> list[str]:
623
+ if self.program_runner.will_be_executed_locally():
624
+ return GeneralUtilities.get_direct_files_of_folder(path)
625
+ else:
626
+ exit_code, stdout, stderr, _ = self.run_program_argsasarray("scfileexists", ["--path", path])
627
+ if exit_code == 0:
628
+ result:list[str]=[]
629
+ for line in stdout.split("\n"):
630
+ normalized_line=line.replace("\r","")
631
+ result.append(normalized_line)
632
+ return result
633
+ else:
634
+ raise ValueError(f"Fatal error occurrs while checking whether file '{path}' exists. StdErr: '{stderr}'")
635
+
620
636
  @GeneralUtilities.check_arguments
621
637
  def is_file(self, path: str) -> bool:
622
638
  if self.program_runner.will_be_executed_locally():
@@ -1277,7 +1293,7 @@ class ScriptCollectionCore:
1277
1293
  return popen
1278
1294
 
1279
1295
  @staticmethod
1280
- def __enqueue_output(file, queue):
1296
+ def __enqueue_output(file:IO, queue:Queue):
1281
1297
  for line in iter(file.readline, ''):
1282
1298
  queue.put(line)
1283
1299
  file.close()
@@ -1432,6 +1448,11 @@ class ScriptCollectionCore:
1432
1448
  except Exception as e:
1433
1449
  raise e
1434
1450
 
1451
+ # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
1452
+ @GeneralUtilities.check_arguments
1453
+ def run_program_with_retry(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, throw_exception_if_exitcode_is_not_zero: bool = True, custom_argument: object = None, interactive: bool = False, print_live_output: bool = False,amount_of_attempts:int=5) -> tuple[int, str, str, int]:
1454
+ return GeneralUtilities.retry_action(lambda: self.run_program(program, arguments,working_directory,verbosity,print_errors_as_information,log_file,timeoutInSeconds,addLogOverhead,title,log_namespace,arguments_for_log,throw_exception_if_exitcode_is_not_zero,custom_argument,interactive,print_live_output), amount_of_attempts)
1455
+
1435
1456
  # Return-values program_runner: Exitcode, StdOut, StdErr, Pid
1436
1457
  @GeneralUtilities.check_arguments
1437
1458
  def run_program(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, throw_exception_if_exitcode_is_not_zero: bool = True, custom_argument: object = None, interactive: bool = False, print_live_output: bool = False) -> tuple[int, str, str, int]:
@@ -1730,7 +1751,7 @@ DNS = {domain}
1730
1751
  folder = os.path.dirname(csproj_file)
1731
1752
  csproj_filename = os.path.basename(csproj_file)
1732
1753
  GeneralUtilities.write_message_to_stderr(f"Check for updates in {csproj_filename}")
1733
- result = self.run_program("dotnet", f"list {csproj_filename} package --outdated", folder)
1754
+ result = self.run_program_with_retry("dotnet", f"list {csproj_filename} package --outdated", folder)
1734
1755
  for line in result[1].replace("\r", "").split("\n"):
1735
1756
  # Relevant output-lines are something like " > NJsonSchema 10.7.0 10.7.0 10.9.0"
1736
1757
  if ">" in line:
@@ -1015,11 +1015,12 @@ class TasksForCommonProjectStructure:
1015
1015
 
1016
1016
  @GeneralUtilities.check_arguments
1017
1017
  def __standardized_tasks_release_artifact(self, information: CreateReleaseInformationForProjectInCommonProjectFormat) -> None:
1018
+ GeneralUtilities.write_message_to_stdout("Release artifacts...")
1018
1019
  project_version = self.__sc.get_semver_version_from_gitversion(information.repository)
1019
1020
  target_folder_base = os.path.join(information.artifacts_folder, information.projectname, project_version)
1020
1021
  GeneralUtilities.ensure_directory_exists(target_folder_base)
1021
1022
 
1022
- self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_productive, information.additional_arguments_file, False, information.export_target, [], True)
1023
+ self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_productive, information.additional_arguments_file, False, information.export_target, [], True, "Productive build")
1023
1024
 
1024
1025
  reference_folder = os.path.join(information.reference_repository, "ReferenceContent")
1025
1026
 
@@ -1243,6 +1244,7 @@ class TasksForCommonProjectStructure:
1243
1244
  def merge_to_main_branch(self, repository_folder: str, source_branch: str = "other/next-release", target_branch: str = "main", verbosity: int = 1, additional_arguments_file: str = None, fast_forward_source_branch: bool = False) -> None:
1244
1245
  # This is an automatization for automatic merges. Usual this merge would be done by a pull request in a sourcecode-version-control-platform
1245
1246
  # (like GitHub, GitLab or Azure DevOps)
1247
+ GeneralUtilities.write_message_to_stdout(f"Merge to main-branch...")
1246
1248
  self.__sc.assert_is_git_repository(repository_folder)
1247
1249
  self.assert_no_uncommitted_changes(repository_folder)
1248
1250
 
@@ -1251,7 +1253,7 @@ class TasksForCommonProjectStructure:
1251
1253
  raise ValueError(f"Can not merge because the source-branch and the target-branch are on the same commit (commit-id: {src_branch_commit_id})")
1252
1254
 
1253
1255
  self.__sc.git_checkout(repository_folder, source_branch)
1254
- self.build_codeunits(repository_folder, verbosity, TasksForCommonProjectStructure.get_qualitycheck_environment_name(), additional_arguments_file, True, None, [], True)
1256
+ self.build_codeunits(repository_folder, verbosity, TasksForCommonProjectStructure.get_qualitycheck_environment_name(), additional_arguments_file, True, None, [], True, "Check if product is buildable")
1255
1257
  self.__sc.git_merge(repository_folder, source_branch, target_branch, False, False, None)
1256
1258
  self.__sc.git_commit(repository_folder, f'Merge branch {source_branch} into {target_branch}', stage_all_changes=True, no_changes_behavior=1)
1257
1259
  self.__sc.git_checkout(repository_folder, target_branch)
@@ -1262,6 +1264,7 @@ class TasksForCommonProjectStructure:
1262
1264
  def merge_to_stable_branch(self, create_release_file: str, createRelease_configuration: CreateReleaseConfiguration):
1263
1265
 
1264
1266
  GeneralUtilities.write_message_to_stdout(f"Create release for project {createRelease_configuration.projectname}.")
1267
+ GeneralUtilities.write_message_to_stdout(f"Merge to stable-branch...")
1265
1268
  self.__sc.assert_is_git_repository(createRelease_configuration.repository_folder)
1266
1269
  folder_of_create_release_file_file = os.path.abspath(os.path.dirname(create_release_file))
1267
1270
 
@@ -1312,7 +1315,7 @@ class TasksForCommonProjectStructure:
1312
1315
  self.__sc.run_program("git", "clean -dfx", information.repository, verbosity=information.verbosity, throw_exception_if_exitcode_is_not_zero=True)
1313
1316
  project_version = self.__sc.get_semver_version_from_gitversion(information.repository)
1314
1317
 
1315
- self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_qualitycheck, information.additional_arguments_file, False, information.export_target, [], True)
1318
+ self.build_codeunits(information.repository, information.verbosity, information.target_environmenttype_for_qualitycheck, information.additional_arguments_file, False, information.export_target, [], True, "Productive build")
1316
1319
 
1317
1320
  self.assert_no_uncommitted_changes(information.repository)
1318
1321
 
@@ -2430,7 +2433,7 @@ class TasksForCommonProjectStructure:
2430
2433
  self.__sc.run_program("docker", f"run --volume {repository_folder}:/Workspace/Repository " + f"-e repositoryfolder=/Workspace/Repository -e verbosity={verbosity} -e targetenvironment={target_environmenttype} {image}", repository_folder)
2431
2434
 
2432
2435
  @GeneralUtilities.check_arguments
2433
- def build_codeunits(self, repository_folder: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, commandline_arguments: list[str] = [], do_git_clean_when_no_changes: bool = False) -> None:
2436
+ def build_codeunits(self, repository_folder: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, commandline_arguments: list[str] = [], do_git_clean_when_no_changes: bool = False, note: str = None) -> None:
2434
2437
  self.__check_target_environmenttype(target_environmenttype)
2435
2438
  self.__sc.assert_is_git_repository(repository_folder)
2436
2439
  repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
@@ -2438,10 +2441,13 @@ class TasksForCommonProjectStructure:
2438
2441
  self.build_specific_codeunits(repository_folder, codeunits, verbosity, target_environmenttype, additional_arguments_file, is_pre_merge, export_target_directory, False, commandline_arguments, do_git_clean_when_no_changes)
2439
2442
 
2440
2443
  @GeneralUtilities.check_arguments
2441
- def build_specific_codeunits(self, repository_folder: str, codeunits: list[str], verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, assume_dependent_codeunits_are_already_built: bool = True, commandline_arguments: list[str] = [], do_git_clean_when_no_changes: bool = False) -> None:
2444
+ def build_specific_codeunits(self, repository_folder: str, codeunits: list[str], verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, assume_dependent_codeunits_are_already_built: bool = True, commandline_arguments: list[str] = [], do_git_clean_when_no_changes: bool = False, note: str = None) -> None:
2445
+ if verbosity>2:
2446
+ GeneralUtilities.write_message_to_stdout(f"Start building codeunits for repository '{repository_folder}'...")
2442
2447
  self.__sc.assert_is_git_repository(repository_folder)
2443
2448
  self.__check_target_environmenttype(target_environmenttype)
2444
2449
  repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
2450
+ repository_name = os.path.dirname(repository_folder)
2445
2451
  contains_uncommitted_changes_at_begin = self.__sc.git_repository_has_uncommitted_changes(repository_folder)
2446
2452
  if contains_uncommitted_changes_at_begin:
2447
2453
  if is_pre_merge:
@@ -2470,6 +2476,11 @@ class TasksForCommonProjectStructure:
2470
2476
  project_version = self.get_version_of_project(repository_folder)
2471
2477
 
2472
2478
  now = datetime.now()
2479
+ message = f"Build codeunits in product {repository_name}..."
2480
+ if note is not None:
2481
+ message = f"{message} ({note})"
2482
+ GeneralUtilities.write_message_to_stdout(message)
2483
+
2473
2484
  if not self.__suport_information_exists(repository_folder, project_version):
2474
2485
  support_time = timedelta(days=365*2+30*3+1) # TODO make this configurable
2475
2486
  until = now + support_time
@@ -2514,6 +2525,11 @@ class TasksForCommonProjectStructure:
2514
2525
  archive_file = os.path.join(os.getcwd(), f"{filename_without_extension}.zip")
2515
2526
  shutil.move(archive_file, target_folder)
2516
2527
 
2528
+ message2 = f"Finished build codeunits in product {repository_name}."
2529
+ if note is not None:
2530
+ message2 = f"{message2} ({note})"
2531
+ GeneralUtilities.write_message_to_stdout(message2)
2532
+
2517
2533
  @GeneralUtilities.check_arguments
2518
2534
  def __do_repository_checks(self, repository_folder: str, project_version: str) -> None:
2519
2535
  self.__sc.assert_is_git_repository(repository_folder)
@@ -2869,11 +2885,11 @@ class TasksForCommonProjectStructure:
2869
2885
  @GeneralUtilities.check_arguments
2870
2886
  def generic_update_dependencies(self, repository_folder: str, verbosity: int = 1):
2871
2887
  # Prepare
2888
+ GeneralUtilities.write_message_to_stdout("Update dependencies...")
2872
2889
  self.__sc.assert_is_git_repository(repository_folder)
2873
2890
  codeunits = self.get_codeunits(repository_folder)
2874
- updated_dependencies = False
2875
2891
  update_dependencies_script_filename = "UpdateDependencies.py"
2876
- self.build_codeunits(repository_folder, target_environmenttype="QualityCheck", do_git_clean_when_no_changes=True) # Required because update dependencies is not always possible for not-buildet codeunits (depends on the programming language or package manager)
2892
+ self.build_codeunits(repository_folder, target_environmenttype="QualityCheck", do_git_clean_when_no_changes=True, note="Prepare dependency-update") # Required because update dependencies is not always possible for not-buildet codeunits (depends on the programming language or package manager)
2877
2893
 
2878
2894
  # update dependencies of resources
2879
2895
  global_scripts_folder = os.path.join(repository_folder, "Other", "Scripts")
@@ -2890,7 +2906,6 @@ class TasksForCommonProjectStructure:
2890
2906
  GeneralUtilities.ensure_directory_exists(os.path.join(update_dependencies_script_folder, "Resources", "CodeAnalysisResult"))
2891
2907
  self.__sc.run_program("python", update_dependencies_script_filename, update_dependencies_script_folder, verbosity)
2892
2908
  if self.__sc.git_repository_has_uncommitted_changes(repository_folder):
2893
- updated_dependencies = True
2894
2909
  version_of_project = self.get_version_of_project(repository_folder)
2895
2910
  changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{version_of_project}.md")
2896
2911
  if not os.path.isfile(changelog_file):
@@ -2903,9 +2918,8 @@ class TasksForCommonProjectStructure:
2903
2918
  GeneralUtilities.write_message_to_stdout(f"Updated dependencies in codeunit {codeunit}.")
2904
2919
  else:
2905
2920
  GeneralUtilities.write_message_to_stdout(f"There are no dependencies to update in codeunit {codeunit}.")
2906
- if updated_dependencies:
2907
- self.build_codeunits(repository_folder, target_environmenttype="QualityCheck", do_git_clean_when_no_changes=True)
2908
- self.__sc.git_commit(repository_folder, "Updated dependencies")
2921
+ self.build_codeunits(repository_folder, target_environmenttype="QualityCheck", do_git_clean_when_no_changes=True, note="Check if product is buildable after dependency-update")
2922
+ self.__sc.git_commit(repository_folder, "Updated dependencies")
2909
2923
 
2910
2924
  class GenericPrepareNewReleaseArguments:
2911
2925
  current_file: str
@@ -2932,8 +2946,8 @@ class TasksForCommonProjectStructure:
2932
2946
  self.__sc.assert_is_git_repository(reference_folder)
2933
2947
  verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_prepare_new_release_arguments.commandline_arguments, 1)
2934
2948
 
2935
- merge_source_branch = "other/next-release" # TODO make this configurable
2936
- main_branch = "main" # TODO make this configurable
2949
+ merge_source_branch = "other/next-release" # maybe this should be configurable
2950
+ main_branch = "main" # maybe this should be configurable
2937
2951
 
2938
2952
  # prepare
2939
2953
  self.assert_no_uncommitted_changes(repository_folder)
@@ -2946,6 +2960,7 @@ class TasksForCommonProjectStructure:
2946
2960
  self.generic_update_dependencies(repository_folder)
2947
2961
  self.assert_no_uncommitted_changes(repository_folder)
2948
2962
 
2963
+ GeneralUtilities.write_message_to_stdout(f"Check reference-repository...")
2949
2964
  now = datetime.now()
2950
2965
  for unsupported_version in self.get_unsupported_versions(repository_folder, now):
2951
2966
  reference_folder = f"{reference_folder}/ReferenceContent/v{unsupported_version}"
@@ -2959,6 +2974,8 @@ class TasksForCommonProjectStructure:
2959
2974
  else:
2960
2975
  self.merge_to_main_branch(repository_folder, merge_source_branch, verbosity=verbosity, fast_forward_source_branch=True)
2961
2976
  self.__sc.git_commit(build_repository_folder, "Updated submodule due to merge to main-branch.")
2977
+ GeneralUtilities.write_message_to_stdout(f"Finished prepare release for {generic_prepare_new_release_arguments.product_name}.")
2978
+
2962
2979
 
2963
2980
  class GenericCreateReleaseArguments():
2964
2981
  current_file: str
@@ -3003,6 +3020,7 @@ class TasksForCommonProjectStructure:
3003
3020
 
3004
3021
  # create release
3005
3022
  new_version = self.merge_to_stable_branch(generic_create_release_arguments.current_file, createReleaseConfiguration)
3023
+ GeneralUtilities.write_message_to_stdout(f"Finished create release for {generic_create_release_arguments.product_name}.")
3006
3024
  return True, new_version
3007
3025
 
3008
3026
  class UpdateHTTPDocumentationArguments:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ScriptCollection
3
- Version: 3.5.65
3
+ Version: 3.5.67
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,16 +1,16 @@
1
- ScriptCollection/Executables.py,sha256=kON_jatJe84iCJj60uUjA-Aj0ytERRe0FUDWbOWUe6s,28089
2
- ScriptCollection/GeneralUtilities.py,sha256=Ah-quoBRLNO3iTCfZaAlN0fhOC42b-UEGYRMW_XxgO0,39438
1
+ ScriptCollection/Executables.py,sha256=jGJIVEjRuOEpcC6ZvCny22DgHZPtr4pmKZj6b-Zn-fA,28514
2
+ ScriptCollection/GeneralUtilities.py,sha256=WSBawT958x_0H-hnPg3S3DGzP3KOQTADtZtP145I-M4,39473
3
3
  ScriptCollection/ProcessesRunner.py,sha256=3mu4ZxzZleQo0Op6o9EYTCFiJfb6kx5ov2YfZfT89mU,1395
4
4
  ScriptCollection/ProgramRunnerBase.py,sha256=2kMIAqdc65UjBAddOZkzy_aFx9h5roZ5a4bQNM6RV6Y,2480
5
5
  ScriptCollection/ProgramRunnerEpew.py,sha256=4pjEd0r9Fcz3TTDv0MdTSd5KkigYXcWUVI1X43regfU,6477
6
6
  ScriptCollection/ProgramRunnerPopen.py,sha256=BPY7-ZMIlqT7JOKz8qlB5c0laF2Js-ijzqk09GxZC48,3821
7
7
  ScriptCollection/RPStream.py,sha256=NRRHL3YSP3D9MuAV2jB_--0KUKCsvJGxeKnxgrRZ9kY,1545
8
- ScriptCollection/ScriptCollectionCore.py,sha256=NrBHbyNrj604n0TxVMeDiFUjy4lprLU4OUskTJOKgJo,111855
9
- ScriptCollection/TasksForCommonProjectStructure.py,sha256=xwEhBfIbrRCMxbklBsQnxnuJ07UQgqYy_fjcv-QXJeQ,213628
8
+ ScriptCollection/ScriptCollectionCore.py,sha256=Gjr-4UES3iYDUuYoBTN8XIaLbuzTq4FyMD_6cuOseAY,113595
9
+ ScriptCollection/TasksForCommonProjectStructure.py,sha256=F6e045gUvSxpOcHk61OVnlod_Zn9JSNXrv6I2SzWoVc,214997
10
10
  ScriptCollection/UpdateCertificates.py,sha256=Eynbgu7k9jLxApP2D_8Il77B6BFjJap6K7oTeEAZYbk,7790
11
11
  ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- ScriptCollection-3.5.65.dist-info/METADATA,sha256=Jqom1sT8VzQZYDWskp7RYVonlTfNhzVcdu3dLahv4Cs,7664
13
- ScriptCollection-3.5.65.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
14
- ScriptCollection-3.5.65.dist-info/entry_points.txt,sha256=wspYVXWH8kon-wRQTAFEO11JoLJ0fEnOIG7tE7R-xtQ,3502
15
- ScriptCollection-3.5.65.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
16
- ScriptCollection-3.5.65.dist-info/RECORD,,
12
+ ScriptCollection-3.5.67.dist-info/METADATA,sha256=jSXXQC_Q1zoKYsvPm38722Tok5dvc3a7dtulFS9j9Uk,7664
13
+ ScriptCollection-3.5.67.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
14
+ ScriptCollection-3.5.67.dist-info/entry_points.txt,sha256=wspYVXWH8kon-wRQTAFEO11JoLJ0fEnOIG7tE7R-xtQ,3502
15
+ ScriptCollection-3.5.67.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
16
+ ScriptCollection-3.5.67.dist-info/RECORD,,