ScriptCollection 3.5.5__py3-none-any.whl → 3.5.7__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.
- ScriptCollection/ScriptCollectionCore.py +17 -33
- ScriptCollection/TasksForCommonProjectStructure.py +120 -51
- {ScriptCollection-3.5.5.dist-info → ScriptCollection-3.5.7.dist-info}/METADATA +1 -1
- {ScriptCollection-3.5.5.dist-info → ScriptCollection-3.5.7.dist-info}/RECORD +7 -7
- {ScriptCollection-3.5.5.dist-info → ScriptCollection-3.5.7.dist-info}/WHEEL +0 -0
- {ScriptCollection-3.5.5.dist-info → ScriptCollection-3.5.7.dist-info}/entry_points.txt +0 -0
- {ScriptCollection-3.5.5.dist-info → ScriptCollection-3.5.7.dist-info}/top_level.txt +0 -0
|
@@ -29,7 +29,7 @@ from .ProgramRunnerBase import ProgramRunnerBase
|
|
|
29
29
|
from .ProgramRunnerPopen import ProgramRunnerPopen
|
|
30
30
|
from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
|
|
31
31
|
|
|
32
|
-
version = "3.5.
|
|
32
|
+
version = "3.5.7"
|
|
33
33
|
__version__ = version
|
|
34
34
|
|
|
35
35
|
|
|
@@ -129,17 +129,14 @@ class ScriptCollectionCore:
|
|
|
129
129
|
|
|
130
130
|
@GeneralUtilities.check_arguments
|
|
131
131
|
def find_file_by_extension(self, folder: str, extension: str):
|
|
132
|
-
result = [file for file in GeneralUtilities.get_direct_files_of_folder(
|
|
133
|
-
folder) if file.endswith(f".{extension}")]
|
|
132
|
+
result = [file for file in GeneralUtilities.get_direct_files_of_folder(folder) if file.endswith(f".{extension}")]
|
|
134
133
|
result_length = len(result)
|
|
135
134
|
if result_length == 0:
|
|
136
|
-
raise FileNotFoundError(
|
|
137
|
-
f"No file available in folder '{folder}' with extension '{extension}'.")
|
|
135
|
+
raise FileNotFoundError(f"No file available in folder '{folder}' with extension '{extension}'.")
|
|
138
136
|
if result_length == 1:
|
|
139
137
|
return result[0]
|
|
140
138
|
else:
|
|
141
|
-
raise ValueError(
|
|
142
|
-
f"Multiple values available in folder '{folder}' with extension '{extension}'.")
|
|
139
|
+
raise ValueError(f"Multiple values available in folder '{folder}' with extension '{extension}'.")
|
|
143
140
|
|
|
144
141
|
@GeneralUtilities.check_arguments
|
|
145
142
|
def commit_is_signed_by_key(self, repository_folder: str, revision_identifier: str, key: str) -> bool:
|
|
@@ -1262,13 +1259,9 @@ class ScriptCollectionCore:
|
|
|
1262
1259
|
working_directory = self.__adapt_workingdirectory(working_directory)
|
|
1263
1260
|
|
|
1264
1261
|
if arguments_for_log is None:
|
|
1265
|
-
arguments_for_log =
|
|
1266
|
-
else:
|
|
1267
|
-
arguments_for_log = ' '.join(arguments_for_log)
|
|
1268
|
-
|
|
1269
|
-
arguments_for_exception_as_string = arguments_for_log
|
|
1262
|
+
arguments_for_log = arguments_as_array
|
|
1270
1263
|
|
|
1271
|
-
arguments_for_log_as_string = arguments_for_log
|
|
1264
|
+
arguments_for_log_as_string: str = ' '.join(arguments_for_log)
|
|
1272
1265
|
cmd = f'{working_directory}>{program} {arguments_for_log_as_string}'
|
|
1273
1266
|
|
|
1274
1267
|
if GeneralUtilities.string_is_none_or_whitespace(title):
|
|
@@ -1278,7 +1271,6 @@ class ScriptCollectionCore:
|
|
|
1278
1271
|
|
|
1279
1272
|
if verbosity >= 3:
|
|
1280
1273
|
GeneralUtilities.write_message_to_stdout(f"Run '{info_for_log}'.")
|
|
1281
|
-
|
|
1282
1274
|
with self.__run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument, interactive) as process:
|
|
1283
1275
|
pid = process.pid
|
|
1284
1276
|
|
|
@@ -1350,14 +1342,8 @@ class ScriptCollectionCore:
|
|
|
1350
1342
|
stdout = GeneralUtilities.bytes_to_string(stdout).replace('\r', '')
|
|
1351
1343
|
stderr = GeneralUtilities.bytes_to_string(stderr).replace('\r', '')
|
|
1352
1344
|
|
|
1353
|
-
if arguments_for_exception_as_string is None:
|
|
1354
|
-
arguments_for_exception_as_string = ' '.join(arguments_as_array)
|
|
1355
|
-
else:
|
|
1356
|
-
arguments_for_exception_as_string = ' '.join(arguments_for_log)
|
|
1357
|
-
|
|
1358
1345
|
if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
|
|
1359
|
-
|
|
1360
|
-
raise ValueError(f"Program '{working_directory}>{program} {arguments_for_exception_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
|
|
1346
|
+
raise ValueError(f"Program '{working_directory}>{program} {arguments_for_log_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
|
|
1361
1347
|
|
|
1362
1348
|
result = (exit_code, stdout, stderr, pid)
|
|
1363
1349
|
return result
|
|
@@ -1543,13 +1529,13 @@ class ScriptCollectionCore:
|
|
|
1543
1529
|
return result
|
|
1544
1530
|
|
|
1545
1531
|
@GeneralUtilities.check_arguments
|
|
1546
|
-
def generate_certificate_authority(self, folder: str, name: str, subj_c: str, subj_st: str, subj_l: str, subj_o: str, subj_ou: str,
|
|
1532
|
+
def generate_certificate_authority(self, folder: str, name: str, subj_c: str, subj_st: str, subj_l: str, subj_o: str, subj_ou: str, days_until_expire: int = None, password: str = None) -> None:
|
|
1547
1533
|
if days_until_expire is None:
|
|
1548
1534
|
days_until_expire = 1825
|
|
1549
1535
|
if password is None:
|
|
1550
1536
|
password = GeneralUtilities.generate_password()
|
|
1551
|
-
|
|
1552
|
-
|
|
1537
|
+
GeneralUtilities.ensure_directory_exists(folder)
|
|
1538
|
+
self.run_program("openssl", f'req -new -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -days {days_until_expire} -nodes -x509 -subj /C={subj_c}/ST={subj_st}/L={subj_l}/O={subj_o}/CN={name}/OU={subj_ou} -passout pass:{password} -keyout {name}.key -out {name}.crt', folder)
|
|
1553
1539
|
|
|
1554
1540
|
@GeneralUtilities.check_arguments
|
|
1555
1541
|
def generate_certificate(self, folder: str, domain: str, filename: str, subj_c: str, subj_st: str, subj_l: str, subj_o: str, subj_ou: str, days_until_expire: int = None, password: str = None) -> None:
|
|
@@ -1598,10 +1584,8 @@ DNS = {domain}
|
|
|
1598
1584
|
ca = os.path.join(ca_folder, ca_name)
|
|
1599
1585
|
password_file = os.path.join(folder, f"{filename}.password")
|
|
1600
1586
|
password = GeneralUtilities.read_text_from_file(password_file)
|
|
1601
|
-
self.run_program(
|
|
1602
|
-
|
|
1603
|
-
self.run_program(
|
|
1604
|
-
"openssl", f'pkcs12 -export -out {filename}.pfx -inkey {filename}.key -in {filename}.crt -password pass:{password}', folder)
|
|
1587
|
+
self.run_program("openssl", f'x509 -req -in {filename}.csr -CA {ca}.crt -CAkey {ca}.key -CAcreateserial -CAserial {ca}.srl -out {filename}.crt -days {days_until_expire} -sha256 -extensions v3_req -extfile {filename}.san.conf', folder)
|
|
1588
|
+
self.run_program("openssl", f'pkcs12 -export -out {filename}.pfx -inkey {filename}.key -in {filename}.crt -password pass:{password}', folder)
|
|
1605
1589
|
|
|
1606
1590
|
@GeneralUtilities.check_arguments
|
|
1607
1591
|
def update_dependencies_of_python_in_requirementstxt_file(self, file: str, verbosity: int):
|
|
@@ -1649,7 +1633,7 @@ DNS = {domain}
|
|
|
1649
1633
|
GeneralUtilities.write_lines_to_file(setup_cfg_file, new_lines)
|
|
1650
1634
|
|
|
1651
1635
|
@GeneralUtilities.check_arguments
|
|
1652
|
-
def update_dependencies_of_dotnet_project(self, csproj_file: str, verbosity: int):
|
|
1636
|
+
def update_dependencies_of_dotnet_project(self, csproj_file: str, verbosity: int, ignored_dependencies: list[str]):
|
|
1653
1637
|
folder = os.path.dirname(csproj_file)
|
|
1654
1638
|
csproj_filename = os.path.basename(csproj_file)
|
|
1655
1639
|
GeneralUtilities.write_message_to_stderr(f"Check for updates in {csproj_filename}")
|
|
@@ -1658,12 +1642,12 @@ DNS = {domain}
|
|
|
1658
1642
|
# Relevant output-lines are something like " > NJsonSchema 10.7.0 10.7.0 10.9.0"
|
|
1659
1643
|
if ">" in line:
|
|
1660
1644
|
package_name = line.replace(">", "").strip().split(" ")[0]
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
"dotnet", f"add {csproj_filename} package {package_name}", folder)
|
|
1645
|
+
if not (ignored_dependencies in package_name):
|
|
1646
|
+
GeneralUtilities.write_message_to_stderr(f"Update package {package_name}")
|
|
1647
|
+
self.run_program("dotnet", f"add {csproj_filename} package {package_name}", folder)
|
|
1664
1648
|
|
|
1665
1649
|
@GeneralUtilities.check_arguments
|
|
1666
|
-
def create_deb_package(self, toolname: str, binary_folder: str, control_file_content: str,
|
|
1650
|
+
def create_deb_package(self, toolname: str, binary_folder: str, control_file_content: str, deb_output_folder: str, verbosity: int, permission_of_executable_file_as_octet_triple: int) -> None:
|
|
1667
1651
|
|
|
1668
1652
|
# prepare
|
|
1669
1653
|
GeneralUtilities.ensure_directory_exists(deb_output_folder)
|
|
@@ -190,7 +190,7 @@ class TasksForCommonProjectStructure:
|
|
|
190
190
|
GeneralUtilities.write_text_to_file(file, re.sub("version = \"\\d+\\.\\d+\\.\\d+\"", f"version = \"{new_version_value}\"", GeneralUtilities.read_text_from_file(file)))
|
|
191
191
|
|
|
192
192
|
@GeneralUtilities.check_arguments
|
|
193
|
-
def standardized_tasks_run_testcases_for_python_codeunit(self, run_testcases_file: str, generate_badges: bool, verbosity: int,
|
|
193
|
+
def standardized_tasks_run_testcases_for_python_codeunit(self, run_testcases_file: str, generate_badges: bool, verbosity: int, targetenvironmenttype: str, commandline_arguments: list[str]) -> None:
|
|
194
194
|
codeunitname: str = Path(os.path.dirname(run_testcases_file)).parent.parent.name
|
|
195
195
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
|
196
196
|
repository_folder: str = str(Path(os.path.dirname(run_testcases_file)).parent.parent.parent.absolute())
|
|
@@ -1003,8 +1003,8 @@ class TasksForCommonProjectStructure:
|
|
|
1003
1003
|
|
|
1004
1004
|
# Copy reference of codeunit to reference-repository
|
|
1005
1005
|
codeunit_version = self.get_version_of_codeunit_folder(os.path.join(information.repository, codeunitname))
|
|
1006
|
-
self.__export_codeunit_reference_content_to_reference_repository(f"v{project_version}", False, reference_folder, information.repository,
|
|
1007
|
-
self.__export_codeunit_reference_content_to_reference_repository("Latest", True, reference_folder, information.repository,
|
|
1006
|
+
self.__export_codeunit_reference_content_to_reference_repository(f"v{project_version}", False, reference_folder, information.repository, codeunitname, information.projectname, codeunit_version, information.public_repository_url, f"v{project_version}")
|
|
1007
|
+
self.__export_codeunit_reference_content_to_reference_repository("Latest", True, reference_folder, information.repository, codeunitname, information.projectname, codeunit_version, information.public_repository_url, information.target_branch_name)
|
|
1008
1008
|
|
|
1009
1009
|
# Generate reference
|
|
1010
1010
|
self.__generate_entire_reference(information.projectname, project_version, reference_folder)
|
|
@@ -1092,8 +1092,7 @@ class TasksForCommonProjectStructure:
|
|
|
1092
1092
|
@GeneralUtilities.check_arguments
|
|
1093
1093
|
def push_nuget_build_artifact(self, push_script_file: str, codeunitname: str, registry_address: str, api_key: str, repository_folder_name: str):
|
|
1094
1094
|
# when pusing to "default public" nuget-server then use registry_address: "nuget.org"
|
|
1095
|
-
build_artifact_folder = GeneralUtilities.resolve_relative_path(
|
|
1096
|
-
f"../../Submodules/{repository_folder_name}/{codeunitname}/Other/Artifacts/BuildResult_NuGet", os.path.dirname(push_script_file))
|
|
1095
|
+
build_artifact_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{repository_folder_name}/{codeunitname}/Other/Artifacts/BuildResult_NuGet", os.path.dirname(push_script_file))
|
|
1097
1096
|
self.__sc.push_nuget_build_artifact(self.__sc.find_file_by_extension(build_artifact_folder, "nupkg"), registry_address, api_key)
|
|
1098
1097
|
|
|
1099
1098
|
@GeneralUtilities.check_arguments
|
|
@@ -1101,18 +1100,40 @@ class TasksForCommonProjectStructure:
|
|
|
1101
1100
|
if self.__sc.git_repository_has_uncommitted_changes(repository_folder):
|
|
1102
1101
|
raise ValueError(f"Repository '{repository_folder}' has uncommitted changes.")
|
|
1103
1102
|
|
|
1103
|
+
@GeneralUtilities.check_arguments
|
|
1104
|
+
def ensure_certificate_authority_for_development_purposes_is_generated(self, script_file: str):
|
|
1105
|
+
folder_of_current_file = os.path.dirname(script_file)
|
|
1106
|
+
product_folder: str = GeneralUtilities.resolve_relative_path("../..", folder_of_current_file)
|
|
1107
|
+
product_name: str = os.path.basename(product_folder)
|
|
1108
|
+
now = datetime.now()
|
|
1109
|
+
ca_name = f"{product_name}CA_{now.year:04}{now.month:02}{now.day:02}{now.hour:02}{now.min:02}{now.second:02}"
|
|
1110
|
+
ca_folder = os.path.join(product_folder, "Other", "Resources", "CA")
|
|
1111
|
+
generate_certificate = True
|
|
1112
|
+
if os.path.isdir(ca_folder):
|
|
1113
|
+
try:
|
|
1114
|
+
ca_file = self.__sc.find_file_by_extension(ca_folder, "crt") # pylint: disable=unused-variable
|
|
1115
|
+
certificate_is_valid = True # TODO check if certificate is not valid
|
|
1116
|
+
generate_certificate = not certificate_is_valid
|
|
1117
|
+
except FileNotFoundError:
|
|
1118
|
+
pass
|
|
1119
|
+
if generate_certificate:
|
|
1120
|
+
self.__sc.generate_certificate_authority(ca_folder, ca_name, "DE", "SubjST", "SubjL", "SubjO", "SubjOU")
|
|
1121
|
+
|
|
1104
1122
|
@GeneralUtilities.check_arguments
|
|
1105
1123
|
def generate_certificate_for_development_purposes_for_external_service(self, service_folder: str, domain: str = None):
|
|
1106
1124
|
testservice_name = os.path.basename(service_folder)
|
|
1107
|
-
|
|
1125
|
+
ca_folder: str = None # TODO
|
|
1126
|
+
self.__generate_certificate_for_development_purposes(testservice_name, os.path.join(service_folder, "Resources"), ca_folder, domain)
|
|
1108
1127
|
|
|
1109
1128
|
@GeneralUtilities.check_arguments
|
|
1110
1129
|
def generate_certificate_for_development_purposes_for_codeunit(self, codeunit_folder: str, domain: str = None):
|
|
1111
1130
|
codeunit_name = os.path.basename(codeunit_folder)
|
|
1112
|
-
self.
|
|
1131
|
+
self.ensure_product_resource_is_imported(codeunit_folder, "CA")
|
|
1132
|
+
ca_folder: str = os.path.join(codeunit_folder, "Other", "Resources", "CA")
|
|
1133
|
+
self.__generate_certificate_for_development_purposes(codeunit_name, os.path.join(codeunit_folder, "Other", "Resources"), ca_folder, domain)
|
|
1113
1134
|
|
|
1114
1135
|
@GeneralUtilities.check_arguments
|
|
1115
|
-
def __generate_certificate_for_development_purposes(self, service_name: str, resources_folder: str, domain: str = None):
|
|
1136
|
+
def __generate_certificate_for_development_purposes(self, service_name: str, resources_folder: str, ca_folder: str, domain: str = None):
|
|
1116
1137
|
if domain is None:
|
|
1117
1138
|
domain = f"{service_name}.test.local"
|
|
1118
1139
|
domain = domain.lower()
|
|
@@ -1120,9 +1141,6 @@ class TasksForCommonProjectStructure:
|
|
|
1120
1141
|
certificate_folder: str = os.path.join(resources_folder, resource_name)
|
|
1121
1142
|
|
|
1122
1143
|
resource_content_filename: str = service_name+resource_name
|
|
1123
|
-
ca_resource_name: str = f"{resource_name}Authority"
|
|
1124
|
-
dev_ca_name = service_name+ca_resource_name
|
|
1125
|
-
ca_folder = os.path.join(resources_folder, ca_resource_name)
|
|
1126
1144
|
certificate_file = os.path.join(certificate_folder, f"{domain}.crt")
|
|
1127
1145
|
unsignedcertificate_file = os.path.join(certificate_folder, f"{domain}.unsigned.crt")
|
|
1128
1146
|
certificate_exists = os.path.exists(certificate_file)
|
|
@@ -1134,15 +1152,22 @@ class TasksForCommonProjectStructure:
|
|
|
1134
1152
|
if generate_new_certificate:
|
|
1135
1153
|
GeneralUtilities.ensure_directory_does_not_exist(certificate_folder)
|
|
1136
1154
|
GeneralUtilities.ensure_directory_exists(certificate_folder)
|
|
1137
|
-
GeneralUtilities.ensure_directory_does_not_exist(ca_folder)
|
|
1138
|
-
GeneralUtilities.ensure_directory_exists(ca_folder)
|
|
1139
1155
|
GeneralUtilities.write_message_to_stdout("Generate TLS-certificate for development-purposes.")
|
|
1140
|
-
self.__sc.generate_certificate_authority(ca_folder, dev_ca_name, "DE", "SubjST", "SubjL", "SubjO", "SubjOU")
|
|
1141
1156
|
self.__sc.generate_certificate(certificate_folder, domain, resource_content_filename, "DE", "SubjST", "SubjL", "SubjO", "SubjOU")
|
|
1142
1157
|
self.__sc.generate_certificate_sign_request(certificate_folder, domain, resource_content_filename, "DE", "SubjST", "SubjL", "SubjO", "SubjOU")
|
|
1143
|
-
self.__sc.
|
|
1158
|
+
ca_name = os.path.basename(self.__sc.find_file_by_extension(ca_folder, "crt"))[:-4]
|
|
1159
|
+
self.__sc.sign_certificate(certificate_folder, ca_folder, ca_name, domain, resource_content_filename)
|
|
1144
1160
|
GeneralUtilities.ensure_file_does_not_exist(unsignedcertificate_file)
|
|
1145
1161
|
|
|
1162
|
+
@GeneralUtilities.check_arguments
|
|
1163
|
+
def ensure_product_resource_is_imported(self, codeunit_folder: str, product_resource_name: str) -> None:
|
|
1164
|
+
product_folder = os.path.dirname(codeunit_folder)
|
|
1165
|
+
source_folder = os.path.join(product_folder, "Other", "Resources", product_resource_name)
|
|
1166
|
+
target_folder = os.path.join(codeunit_folder, "Other", "Resources", product_resource_name)
|
|
1167
|
+
GeneralUtilities.ensure_directory_does_not_exist(target_folder)
|
|
1168
|
+
GeneralUtilities.ensure_directory_exists(target_folder)
|
|
1169
|
+
GeneralUtilities.copy_content_of_folder(source_folder, target_folder)
|
|
1170
|
+
|
|
1146
1171
|
@GeneralUtilities.check_arguments
|
|
1147
1172
|
def get_codeunits(self, repository_folder: str, ignore_disabled_codeunits: bool = True) -> list[str]:
|
|
1148
1173
|
result: list[str] = []
|
|
@@ -1219,8 +1244,7 @@ class TasksForCommonProjectStructure:
|
|
|
1219
1244
|
# hint: arguments can be overwritten by commandline_arguments
|
|
1220
1245
|
folder_of_this_file = os.path.dirname(create_release_file)
|
|
1221
1246
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
|
1222
|
-
self.__sc.run_program("python", f"CreateRelease.py --overwrite_verbosity {str(verbosity)}",
|
|
1223
|
-
folder_of_this_file, verbosity=verbosity, log_file=logfile, addLogOverhead=addLogOverhead)
|
|
1247
|
+
self.__sc.run_program("python", f"CreateRelease.py --overwrite_verbosity {str(verbosity)}", folder_of_this_file, verbosity=verbosity, log_file=logfile, addLogOverhead=addLogOverhead)
|
|
1224
1248
|
|
|
1225
1249
|
@GeneralUtilities.check_arguments
|
|
1226
1250
|
def __standardized_tasks_merge_to_stable_branch(self, information: MergeToStableBranchInformationForProjectInCommonProjectFormat) -> str:
|
|
@@ -1367,7 +1391,7 @@ class TasksForCommonProjectStructure:
|
|
|
1367
1391
|
|
|
1368
1392
|
# Check codeunit-conformity
|
|
1369
1393
|
# TODO check if foldername=="<codeunitname>[.codeunit.xml]" == <codeunitname> in file
|
|
1370
|
-
supported_codeunitspecificationversion = "2.
|
|
1394
|
+
supported_codeunitspecificationversion = "2.8.0" # should always be the latest version of the ProjectTemplates-repository
|
|
1371
1395
|
codeunit_file = os.path.join(codeunit_folder, f"{codeunit_name}.codeunit.xml")
|
|
1372
1396
|
if not os.path.isfile(codeunit_file):
|
|
1373
1397
|
raise ValueError(f'Codeunitfile "{codeunit_file}" does not exist.')
|
|
@@ -1383,6 +1407,7 @@ class TasksForCommonProjectStructure:
|
|
|
1383
1407
|
raise ValueError(f"ScriptCollection only supports processing codeunits with codeunit-specification-version={supported_codeunitspecificationversion}.")
|
|
1384
1408
|
schemaLocation = root.xpath('//cps:codeunit/@xsi:schemaLocation', namespaces=namespaces)[0]
|
|
1385
1409
|
xmlschema.validate(codeunit_file, schemaLocation)
|
|
1410
|
+
# TODO check if the properties codeunithastestablesourcecode, codeunithasupdatabledependencies, throwexceptionifcodeunitfilecannotbevalidated, developmentState and description exist and the values are valid
|
|
1386
1411
|
except Exception as exception:
|
|
1387
1412
|
if self.codeunit_throws_exception_if_codeunitfile_is_not_validatable(codeunit_file):
|
|
1388
1413
|
raise exception
|
|
@@ -1398,8 +1423,10 @@ class TasksForCommonProjectStructure:
|
|
|
1398
1423
|
# Check for mandatory files
|
|
1399
1424
|
files = ["Other/Build/Build.py", "Other/QualityCheck/Linting.py", "Other/Reference/GenerateReference.py"]
|
|
1400
1425
|
if self.codeunit_has_testable_sourcecode(codeunit_file):
|
|
1426
|
+
# TODO check if the testsettings-section appears in the codeunit-file
|
|
1401
1427
|
files.append("Other/QualityCheck/RunTestcases.py")
|
|
1402
1428
|
if self.codeunit_has_updatable_dependencies(codeunit_file):
|
|
1429
|
+
# TODO check if the updatesettings-section appears in the codeunit-file
|
|
1403
1430
|
files.append("Other/UpdateDependencies.py")
|
|
1404
1431
|
for file in files:
|
|
1405
1432
|
combined_file = os.path.join(codeunit_folder, file)
|
|
@@ -1494,7 +1521,7 @@ class TasksForCommonProjectStructure:
|
|
|
1494
1521
|
build_script_folder = os.path.dirname(build_script_file)
|
|
1495
1522
|
codeunit_folder = GeneralUtilities.resolve_relative_path("../..", build_script_folder)
|
|
1496
1523
|
GeneralUtilities.ensure_directory_does_not_exist(f"{codeunit_folder}/.angular")
|
|
1497
|
-
self.
|
|
1524
|
+
self.standardized_tasks_build_for_node_codeunit(build_script_file, build_environment_target_type, verbosity, commandline_arguments)
|
|
1498
1525
|
|
|
1499
1526
|
@GeneralUtilities.check_arguments
|
|
1500
1527
|
def standardized_tasks_build_for_node_codeunit(self, build_script_file: str, build_environment_target_type: str, verbosity: int, commandline_arguments: list[str]) -> None:
|
|
@@ -1845,17 +1872,33 @@ class TasksForCommonProjectStructure:
|
|
|
1845
1872
|
for codeunit in codeunits:
|
|
1846
1873
|
artifact_files.append(self.__sc.find_file_by_extension(f"{build_artifacts_folder}\\{productname}\\{projectversion}\\{codeunit}", "Productive.Artifacts.zip"))
|
|
1847
1874
|
changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{projectversion}.md")
|
|
1848
|
-
self.__sc.run_program_argsasarray("gh", ["release", "create", f"v{projectversion}", "--repo", github_repo,
|
|
1875
|
+
self.__sc.run_program_argsasarray("gh", ["release", "create", f"v{projectversion}", "--repo", github_repo, "--notes-file", changelog_file, "--title", f"Release v{projectversion}"]+artifact_files, verbosity=verbosity)
|
|
1876
|
+
|
|
1877
|
+
@GeneralUtilities.check_arguments
|
|
1878
|
+
def get_dependencies_which_are_ignored_from_updates(self, codeunit_folder: str, print_warnings_for_ignored_dependencies: bool) -> list[str]:
|
|
1879
|
+
namespaces = {'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure',
|
|
1880
|
+
'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
|
|
1881
|
+
codeunit_name = os.path.basename(codeunit_folder)
|
|
1882
|
+
codeunit_file = os.path.join(codeunit_folder, f"{codeunit_name}.codeunit.xml")
|
|
1883
|
+
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
1884
|
+
ignoreddependencies = root.xpath('//cps:codeunit/cps:properties/cps:updatesettings/cps:ignoreddependencies/cps:ignoreddependency', namespaces=namespaces)
|
|
1885
|
+
result = [x.text.replace("\\n", "").replace("\\r", "").replace("\n", "").replace("\r", "").strip() for x in ignoreddependencies]
|
|
1886
|
+
if print_warnings_for_ignored_dependencies and len(result > 0):
|
|
1887
|
+
GeneralUtilities.write_message_to_stderr(f"Warning: Codeunit {codeunit_name} contains the following dependencies which will are ignoed for automatic updates: "+', '.join(result))
|
|
1888
|
+
return result
|
|
1849
1889
|
|
|
1850
1890
|
@GeneralUtilities.check_arguments
|
|
1851
1891
|
def update_dependencies_of_typical_flutter_codeunit(self, update_script_file: str, verbosity: int, cmd_args: list[str]) -> None:
|
|
1852
|
-
|
|
1892
|
+
codeunit_folder = GeneralUtilities.resolve_relative_path("..", os.path.dirname(update_script_file))
|
|
1893
|
+
ignored_dependencies = self.get_dependencies_which_are_ignored_from_updates(codeunit_folder, True)
|
|
1894
|
+
# TODO implement
|
|
1853
1895
|
|
|
1854
1896
|
@GeneralUtilities.check_arguments
|
|
1855
1897
|
def update_dependencies_of_typical_python_codeunit(self, update_script_file: str, verbosity: int, cmd_args: list[str]) -> None:
|
|
1856
|
-
# TODO generalize and add option to ignore certain dependencies and to only update patch-versions
|
|
1857
|
-
verbosity = self.get_verbosity_from_commandline_arguments(cmd_args, verbosity)
|
|
1858
1898
|
codeunit_folder = GeneralUtilities.resolve_relative_path("..", os.path.dirname(update_script_file))
|
|
1899
|
+
ignored_dependencies = self.get_dependencies_which_are_ignored_from_updates(codeunit_folder, True)
|
|
1900
|
+
# TODO consider ignored_dependencies
|
|
1901
|
+
verbosity = self.get_verbosity_from_commandline_arguments(cmd_args, verbosity)
|
|
1859
1902
|
self.__sc.update_dependencies_of_python_in_setupcfg_file(os.path.join(codeunit_folder, "setup.cfg"), verbosity)
|
|
1860
1903
|
development_requirements_file = os.path.join(codeunit_folder, "requirements.txt")
|
|
1861
1904
|
if (os.path.isfile(development_requirements_file)):
|
|
@@ -1863,22 +1906,25 @@ class TasksForCommonProjectStructure:
|
|
|
1863
1906
|
|
|
1864
1907
|
@GeneralUtilities.check_arguments
|
|
1865
1908
|
def update_dependencies_of_typical_dotnet_codeunit(self, update_script_file: str, verbosity: int, cmd_args: list[str]) -> None:
|
|
1866
|
-
# TODO generalize and add option to ignore certain dependencies
|
|
1867
|
-
verbosity = self.get_verbosity_from_commandline_arguments(cmd_args, verbosity)
|
|
1868
1909
|
codeunit_folder = GeneralUtilities.resolve_relative_path("..", os.path.dirname(update_script_file))
|
|
1910
|
+
ignored_dependencies = self.get_dependencies_which_are_ignored_from_updates(codeunit_folder, True)
|
|
1911
|
+
verbosity = self.get_verbosity_from_commandline_arguments(cmd_args, verbosity)
|
|
1869
1912
|
codeunit_name = os.path.basename(codeunit_folder)
|
|
1870
1913
|
|
|
1871
1914
|
build_folder = os.path.join(codeunit_folder, "Other", "Build")
|
|
1872
1915
|
self.__sc.run_program("python", "Build.py", build_folder, verbosity)
|
|
1873
1916
|
|
|
1874
1917
|
csproj_file = os.path.join(codeunit_folder, codeunit_name, f"{codeunit_name}.csproj")
|
|
1875
|
-
self.__sc.update_dependencies_of_dotnet_project(csproj_file, verbosity)
|
|
1918
|
+
self.__sc.update_dependencies_of_dotnet_project(csproj_file, verbosity, ignored_dependencies)
|
|
1876
1919
|
test_csproj_file = os.path.join(codeunit_folder, f"{codeunit_name}Tests", f"{codeunit_name}Tests.csproj")
|
|
1877
|
-
self.__sc.update_dependencies_of_dotnet_project(test_csproj_file, verbosity)
|
|
1920
|
+
self.__sc.update_dependencies_of_dotnet_project(test_csproj_file, verbosity, ignored_dependencies)
|
|
1878
1921
|
|
|
1879
1922
|
@GeneralUtilities.check_arguments
|
|
1880
1923
|
def update_dependencies_of_typical_node_codeunit(self, update_script_file: str, verbosity: int, cmd_args: list[str]) -> None:
|
|
1881
1924
|
current_folder = os.path.dirname(update_script_file)
|
|
1925
|
+
codeunit_folder = GeneralUtilities.resolve_relative_path("..", os.path.dirname(update_script_file))
|
|
1926
|
+
ignored_dependencies = self.get_dependencies_which_are_ignored_from_updates(codeunit_folder, True)
|
|
1927
|
+
# TODO consider ignored_dependencies
|
|
1882
1928
|
result = self.run_with_epew("npm", "outdated", current_folder, verbosity, throw_exception_if_exitcode_is_not_zero=False)
|
|
1883
1929
|
if result[0] == 0:
|
|
1884
1930
|
return # all dependencies up to date
|
|
@@ -1963,9 +2009,9 @@ class TasksForCommonProjectStructure:
|
|
|
1963
2009
|
@GeneralUtilities.check_arguments
|
|
1964
2010
|
def create_artifact_for_development_certificate(self, codeunit_folder: str):
|
|
1965
2011
|
ce_source_folder = GeneralUtilities.resolve_relative_path("Other/Resources/DevelopmentCertificate", codeunit_folder)
|
|
1966
|
-
ca_source_folder = GeneralUtilities.resolve_relative_path("Other/Resources/
|
|
2012
|
+
ca_source_folder = GeneralUtilities.resolve_relative_path("Other/Resources/CA", codeunit_folder)
|
|
1967
2013
|
ce_target_folder = GeneralUtilities.resolve_relative_path("Other/Artifacts/DevelopmentCertificate", codeunit_folder)
|
|
1968
|
-
ca_target_folder = GeneralUtilities.resolve_relative_path("Other/Artifacts/
|
|
2014
|
+
ca_target_folder = GeneralUtilities.resolve_relative_path("Other/Artifacts/A", codeunit_folder)
|
|
1969
2015
|
|
|
1970
2016
|
GeneralUtilities.ensure_directory_exists(ce_target_folder)
|
|
1971
2017
|
GeneralUtilities.copy_content_of_folder(ce_source_folder, ce_target_folder)
|
|
@@ -2006,8 +2052,7 @@ class TasksForCommonProjectStructure:
|
|
|
2006
2052
|
# TODO handle additional_arguments_file
|
|
2007
2053
|
# TODO add option to allow building different codeunits in same project with different images due to their demands
|
|
2008
2054
|
# TODO check if image provides all demands of codeunit
|
|
2009
|
-
self.__sc.run_program(
|
|
2010
|
-
"docker", f"run --volume {repository_folder}:/Workspace/Repository " + f"-e repositoryfolder=/Workspace/Repository -e verbosity={verbosity} -e targetenvironment={target_environmenttype} {image}", repository_folder)
|
|
2055
|
+
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)
|
|
2011
2056
|
|
|
2012
2057
|
@GeneralUtilities.check_arguments
|
|
2013
2058
|
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] = []) -> None:
|
|
@@ -2025,6 +2070,14 @@ class TasksForCommonProjectStructure:
|
|
|
2025
2070
|
raise ValueError(f'Repository "{repository_folder}" has uncommitted changes.')
|
|
2026
2071
|
subfolders = [os.path.join(repository_folder, codeunit) for codeunit in codeunits]
|
|
2027
2072
|
codeunits_with_dependent_codeunits: dict[str, set[str]] = dict[str, set[str]]()
|
|
2073
|
+
|
|
2074
|
+
project_resources_folder = os.path.join(repository_folder, "Other", "Scripts")
|
|
2075
|
+
PrepareBuildCodeunits_script_name = "PrepareBuildCodeunits.py"
|
|
2076
|
+
prepare_build_codeunits_scripts = os.path.join(project_resources_folder, PrepareBuildCodeunits_script_name)
|
|
2077
|
+
if os.path.isfile(prepare_build_codeunits_scripts):
|
|
2078
|
+
GeneralUtilities.write_message_to_stdout(f'Run "{PrepareBuildCodeunits_script_name}"')
|
|
2079
|
+
self.__sc.run_program("python", f"{PrepareBuildCodeunits_script_name}", project_resources_folder)
|
|
2080
|
+
|
|
2028
2081
|
for subfolder in subfolders:
|
|
2029
2082
|
codeunit_name: str = os.path.basename(subfolder)
|
|
2030
2083
|
codeunit_file = os.path.join(subfolder, f"{codeunit_name}.codeunit.xml")
|
|
@@ -2250,7 +2303,7 @@ class TasksForCommonProjectStructure:
|
|
|
2250
2303
|
deb_output_folder = GeneralUtilities.resolve_relative_path("Other/Artifacts/BuildResult_Deb", codeunit_folder)
|
|
2251
2304
|
control_file = GeneralUtilities.resolve_relative_path("Other/Build/DebControlFile.txt", codeunit_folder)
|
|
2252
2305
|
installedsize = self.calculate_deb_package_size(binary_folder)
|
|
2253
|
-
control_file_content = self.load_deb_control_file_content(control_file, codeunit_name, self.get_version_of_codeunit_folder(codeunit_folder),
|
|
2306
|
+
control_file_content = self.load_deb_control_file_content(control_file, codeunit_name, self.get_version_of_codeunit_folder(codeunit_folder), installedsize, maintainername, maintaineremail, description)
|
|
2254
2307
|
self.__sc.create_deb_package(codeunit_name, binary_folder, control_file_content, deb_output_folder, verbosity, 555)
|
|
2255
2308
|
|
|
2256
2309
|
@GeneralUtilities.check_arguments
|
|
@@ -2425,6 +2478,7 @@ class TasksForCommonProjectStructure:
|
|
|
2425
2478
|
GeneralUtilities.ensure_directory_exists(os.path.join(update_dependencies_script_folder, "Resources", "CodeAnalysisResult"))
|
|
2426
2479
|
self.__sc.run_program("python", "UpdateDependencies.py", update_dependencies_script_folder, verbosity)
|
|
2427
2480
|
if self.__sc.git_repository_has_uncommitted_changes(repository_folder):
|
|
2481
|
+
updated_dependencies = True
|
|
2428
2482
|
version_of_project = self.get_version_of_project(repository_folder)
|
|
2429
2483
|
changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{version_of_project}.md")
|
|
2430
2484
|
if not os.path.isfile(changelog_file):
|
|
@@ -2435,7 +2489,6 @@ class TasksForCommonProjectStructure:
|
|
|
2435
2489
|
- Updated dependencies.
|
|
2436
2490
|
""")
|
|
2437
2491
|
GeneralUtilities.write_message_to_stdout(f"Updated dependencies in codeunit {codeunit}.")
|
|
2438
|
-
updated_dependencies = True
|
|
2439
2492
|
else:
|
|
2440
2493
|
GeneralUtilities.write_message_to_stdout(f"There are no dependencies to update in codeunit {codeunit}.")
|
|
2441
2494
|
if updated_dependencies:
|
|
@@ -2461,15 +2514,26 @@ class TasksForCommonProjectStructure:
|
|
|
2461
2514
|
|
|
2462
2515
|
repository_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{generic_prepare_new_release_arguments.product_name}", folder_of_this_file)
|
|
2463
2516
|
verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_prepare_new_release_arguments.commandline_arguments, 1)
|
|
2464
|
-
|
|
2517
|
+
|
|
2518
|
+
merge_source_branch = "other/next-release" # TODO make this configurable
|
|
2519
|
+
main_branch = "main" # TODO make this configurable
|
|
2465
2520
|
|
|
2466
2521
|
# prepare
|
|
2467
2522
|
self.assert_no_uncommitted_changes(repository_folder)
|
|
2468
2523
|
self.__sc.git_checkout(repository_folder, merge_source_branch)
|
|
2524
|
+
self.assert_no_uncommitted_changes(repository_folder)
|
|
2525
|
+
|
|
2469
2526
|
if "--dependencyupdate" in generic_prepare_new_release_arguments.commandline_arguments:
|
|
2470
2527
|
self.generic_update_dependencies(repository_folder)
|
|
2471
|
-
|
|
2472
|
-
|
|
2528
|
+
self.assert_no_uncommitted_changes(repository_folder)
|
|
2529
|
+
|
|
2530
|
+
merge_source_branch_commit_id = self.__sc.git_get_commit_id(repository_folder, merge_source_branch)
|
|
2531
|
+
main_branch_commit_id = self.__sc.git_get_commit_id(repository_folder, main_branch)
|
|
2532
|
+
if merge_source_branch_commit_id == main_branch_commit_id:
|
|
2533
|
+
GeneralUtilities.write_message_to_stdout("Release will not be prepared because there are no changed which can be released.")
|
|
2534
|
+
else:
|
|
2535
|
+
self.merge_to_main_branch(repository_folder, merge_source_branch, verbosity=verbosity, fast_forward_source_branch=True)
|
|
2536
|
+
self.__sc.git_commit(build_repository_folder, "Updated submodule due to merge to main-branch.")
|
|
2473
2537
|
|
|
2474
2538
|
class GenericCreateReleaseArguments():
|
|
2475
2539
|
current_file: str
|
|
@@ -2486,28 +2550,33 @@ class TasksForCommonProjectStructure:
|
|
|
2486
2550
|
self.commandline_arguments = commandline_arguments
|
|
2487
2551
|
|
|
2488
2552
|
@GeneralUtilities.check_arguments
|
|
2489
|
-
def generic_create_release(self, generic_create_release_arguments: GenericCreateReleaseArguments) -> str:
|
|
2553
|
+
def generic_create_release(self, generic_create_release_arguments: GenericCreateReleaseArguments) -> tuple[bool, str]:
|
|
2490
2554
|
folder_of_this_file = os.path.dirname(generic_create_release_arguments.current_file)
|
|
2491
2555
|
build_repository_folder = GeneralUtilities.resolve_relative_path("../..", folder_of_this_file)
|
|
2492
2556
|
repository_folder_name = generic_create_release_arguments.product_name
|
|
2493
2557
|
repository_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{generic_create_release_arguments.product_name}", folder_of_this_file)
|
|
2494
|
-
additional_arguments_file = os.path.join(folder_of_this_file, "AdditionalArguments.configuration")
|
|
2495
|
-
verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_create_release_arguments.commandline_arguments, 1)
|
|
2496
|
-
createReleaseConfiguration: CreateReleaseConfiguration = CreateReleaseConfiguration(
|
|
2497
|
-
generic_create_release_arguments.product_name, generic_create_release_arguments.common_remote_name, generic_create_release_arguments.artifacts_target_folder, folder_of_this_file, verbosity, repository_folder, additional_arguments_file, repository_folder_name)
|
|
2498
|
-
|
|
2499
|
-
reference_repo: str = os.path.join(build_repository_folder, "Submodules", f"{generic_create_release_arguments.product_name}Reference")
|
|
2500
|
-
self.__sc.git_commit(reference_repo, "Updated reference")
|
|
2501
|
-
|
|
2502
|
-
self.__sc.git_commit(build_repository_folder, "Updated submodule")
|
|
2503
2558
|
|
|
2504
|
-
#
|
|
2505
|
-
|
|
2559
|
+
merge_source_branch = "main" # TODO make this configurable
|
|
2560
|
+
main_branch = "stable" # TODO make this configurable
|
|
2506
2561
|
|
|
2507
|
-
|
|
2508
|
-
|
|
2562
|
+
additional_arguments_file = os.path.join(folder_of_this_file, "AdditionalArguments.configuration")
|
|
2563
|
+
verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_create_release_arguments.commandline_arguments, 1)
|
|
2564
|
+
createReleaseConfiguration: CreateReleaseConfiguration = CreateReleaseConfiguration(generic_create_release_arguments.product_name, generic_create_release_arguments.common_remote_name, generic_create_release_arguments.artifacts_target_folder, folder_of_this_file, verbosity, repository_folder, additional_arguments_file, repository_folder_name)
|
|
2509
2565
|
|
|
2510
|
-
|
|
2566
|
+
merge_source_branch_commit_id = self.__sc.git_get_commit_id(repository_folder, merge_source_branch)
|
|
2567
|
+
main_branch_commit_id = self.__sc.git_get_commit_id(repository_folder, main_branch)
|
|
2568
|
+
if merge_source_branch_commit_id == main_branch_commit_id:
|
|
2569
|
+
GeneralUtilities.write_message_to_stdout("Release will not be done because there are no changed which can be released.")
|
|
2570
|
+
return False, None
|
|
2571
|
+
else:
|
|
2572
|
+
reference_repo: str = os.path.join(build_repository_folder, "Submodules", f"{generic_create_release_arguments.product_name}Reference")
|
|
2573
|
+
self.__sc.git_commit(reference_repo, "Updated reference")
|
|
2574
|
+
self.__sc.git_commit(build_repository_folder, "Updated submodule")
|
|
2575
|
+
|
|
2576
|
+
# create release
|
|
2577
|
+
new_version = self.merge_to_stable_branch(generic_create_release_arguments.current_file, createReleaseConfiguration)
|
|
2578
|
+
self.__sc.git_checkout(repository_folder, merge_source_branch)
|
|
2579
|
+
return True, new_version
|
|
2511
2580
|
|
|
2512
2581
|
class UpdateHTTPDocumentationArguments:
|
|
2513
2582
|
current_file: str
|
|
@@ -5,12 +5,12 @@ ScriptCollection/ProgramRunnerBase.py,sha256=W4MaDroJHARRtcvPkBC2AS_qgDSRIqOkMvG
|
|
|
5
5
|
ScriptCollection/ProgramRunnerEpew.py,sha256=lx_jR3W8KavBpZo44u2FrOca_EWWgUb3_w_YKGRrAyM,6471
|
|
6
6
|
ScriptCollection/ProgramRunnerPopen.py,sha256=5QFplojwfGS8_WdYrg5nE6__QFB5iaMA0EP8OGfgPoY,3526
|
|
7
7
|
ScriptCollection/RPStream.py,sha256=NRRHL3YSP3D9MuAV2jB_--0KUKCsvJGxeKnxgrRZ9kY,1545
|
|
8
|
-
ScriptCollection/ScriptCollectionCore.py,sha256
|
|
9
|
-
ScriptCollection/TasksForCommonProjectStructure.py,sha256=
|
|
8
|
+
ScriptCollection/ScriptCollectionCore.py,sha256=-HpxrPjlHNPv1Ud4Pxh-vH-dEJJGvw4jyI-_5xsGOKo,96539
|
|
9
|
+
ScriptCollection/TasksForCommonProjectStructure.py,sha256=jExRHYZQfRJWY4NDboREI1NfYjHMvIabsKZ05qi8DoA,186707
|
|
10
10
|
ScriptCollection/UpdateCertificates.py,sha256=lfmVuify-Fqq-vGJusDDUsJVhA-rVLwW2Jx9iLwmkBo,7916
|
|
11
11
|
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
ScriptCollection-3.5.
|
|
13
|
-
ScriptCollection-3.5.
|
|
14
|
-
ScriptCollection-3.5.
|
|
15
|
-
ScriptCollection-3.5.
|
|
16
|
-
ScriptCollection-3.5.
|
|
12
|
+
ScriptCollection-3.5.7.dist-info/METADATA,sha256=cG_gwtTzfmBIksPGZK3VGJZ0Tafat4-G1UeTuQSuyts,7679
|
|
13
|
+
ScriptCollection-3.5.7.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
|
|
14
|
+
ScriptCollection-3.5.7.dist-info/entry_points.txt,sha256=dwvB9HRGvqst5xlYIGmmwuFN7lBKhxvndmnNrQOfu8w,2153
|
|
15
|
+
ScriptCollection-3.5.7.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
|
16
|
+
ScriptCollection-3.5.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|